Kozea / WeasyPrint

The awesome document factory
https://weasyprint.org
BSD 3-Clause "New" or "Revised" License
7.09k stars 674 forks source link

Installation instructions for Linux #1045

Closed Tontyna closed 3 years ago

Tontyna commented 4 years ago

Unless we assume that THE AVERAGE LINUX USER is somebody who likes to tinker with her system and knows what's going on, the installation instructions for Linux are not exhaustive enough. At least on Ubuntu 18.04 they don't work out of the box.

Don't know nothing (yet) about other distros, but on Ubuntu I'd never tell anybody to run pip as sudo -- I didn't do it but I'm sure that kittens will die when pip installs into root's USER_SITE site-packages folder (afaik --user is the default option for pip on Ubuntu).

To use a virtual environment the python3-venv system package must be installed, too,

After the venv is activated one should update the outdated pip

python -m pip install --upgrade pip setuptools

When I tried to pip install WeasyPrint it failed with the well-known animosities of cairocffi not being able to run pycparser or building a wheel for pycparser or whatever ... "ERROR: Command errored out with exit status 1."

I'd really like to know what's wrong with cairocffi. Ok, no problem. Solution is to install step-wise:

pip install cffi
pip install cairoffi
pip install weasyprint

Volunteering to improve install.rst I'd like to know whether these issues apply to other Linux distros too.

liZe commented 4 years ago

Disclaimer: I really think that the whole documentation has to be rewritten and/or reorganized, and the Install page should be the first one to change.

Unless we assume that THE AVERAGE LINUX USER is somebody who likes to tinker with her system and knows what's going on, the installation instructions for Linux are not exhaustive enough. At least on Ubuntu 18.04 they don't work out of the box.

Nevertheless, I’ll try to defend the current documentation :smile:.

(We have to add in the documentation that WeasyPrint is now packaged for Ubuntu. Average Linux users will just have to launch apt install weasyprint :tada:.)

Don't know nothing (yet) about other distros, but on Ubuntu I'd never tell anybody to run pip as sudo -- I didn't do it but I'm sure that kittens will die when pip installs into root's USER_SITE site-packages folder (afaik --user is the default option for pip on Ubuntu).

It’s true, nobody does this anymore. But this was good advice in 2013, when 1145958 was committed :wink:.

To use a virtual environment the python3-venv system package must be installed, too,

You’re right. I really don’t know why it’s a separate package in Debian/Ubuntu, even if it’s in the standard library since Python 3.3.

After the venv is activated one should update the outdated pip

You can, but it’s not mandatory. (Is it?)

When I tried to pip install WeasyPrint it failed with the well-known animosities of cairocffi not being able to run pycparser or building a wheel for pycparser or whatever ... "ERROR: Command errored out with exit status 1."

I have red scary red lines with "Failed building wheel for cairocffi" and "Failed building wheel for pycparser", but the packages are installed and everything works out of the box. I’ve created a fresh virtual environment on my Ubuntu 18.04.3 computer, and it works. Could you please paste the whole trace?

Tontyna commented 4 years ago

WeasyPrint is now packaged for Ubuntu.

... for Ubuntu Focal.

I really don’t know why it’s a separate package in Debian/Ubuntu, even if it’s in the standard library since Python 3.3.

venv is indeed present in the system standard library but without python3-venv it groans about missing ensurepip. python3-venv installs the ensurepip module in the standard library folder. There are comments about this in (the special Ubuntu versions of) venv/__init__.py and ensurepip/__init__.py. They try hard to protect their system python!

Updating pip and setuptools isn't mandatory, of course. In fact: With outdated pip-9.0.1 setuptools-39.0.1 the WeasyPrint installation succeeds (though there are those 2 red scary lines you mentioned). The upgraded pip-20.0.2 setuptools-45.1.0 fails!

Trace of failing pip install weasyprint

    $ pip install WeasyPrint
Collecting WeasyPrint
  Using cached WeasyPrint-51-py3-none-any.whl (359 kB)
Collecting Pyphen>=0.9.1
  Using cached Pyphen-0.9.5-py2.py3-none-any.whl (3.0 MB)
Collecting CairoSVG>=2.4.0
  Using cached CairoSVG-2.4.2-py3-none-any.whl (50 kB)
Collecting cssselect2>=0.1
  Using cached cssselect2-0.2.2-py2.py3-none-any.whl (31 kB)
Collecting cffi>=0.6
  Using cached cffi-1.13.2-cp36-cp36m-manylinux1_x86_64.whl (397 kB)
Collecting html5lib>=0.999999999
  Using cached html5lib-1.0.1-py2.py3-none-any.whl (117 kB)
Collecting cairocffi>=0.9.0
  Using cached cairocffi-1.1.0.tar.gz (68 kB)
    ERROR: Command errored out with exit status 1:
     command: /home/xxxx/Python/env36/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-3cwd09rc/cairocffi/setup.py'"'"'; __file__='"'"'/tmp/pip-install-3cwd09rc/cairocffi/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-3cwd09rc/cairocffi/pip-egg-info
         cwd: /tmp/pip-install-3cwd09rc/cairocffi/
    Complete output (46 lines):
    WARNING: The wheel package is not available.
    WARNING: The wheel package is not available.
    WARNING: The wheel package is not available.
      ERROR: Command errored out with exit status 1:
       command: /home/xxxx/Python/env36/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-wheel-m6b9k2vl/pycparser/setup.py'"'"'; __file__='"'"'/tmp/pip-wheel-m6b9k2vl/pycparser/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-3kx87ngb
           cwd: /tmp/pip-wheel-m6b9k2vl/pycparser/
      Complete output (6 lines):
      usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
         or: setup.py --help [cmd1 cmd2 ...]
         or: setup.py --help-commands
         or: setup.py cmd --help

      error: invalid command 'bdist_wheel'
      ----------------------------------------
      ERROR: Failed building wheel for pycparser
    ERROR: Failed to build one or more wheels
    Traceback (most recent call last):
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/installer.py", line 128, in fetch_build_egg
        subprocess.check_call(cmd)
      File "/usr/lib/python3.6/subprocess.py", line 311, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['/home/xxxx/Python/env36/bin/python', '-m', 'pip', '--disable-pip-version-check', 'wheel', '--no-deps', '-w', '/tmp/tmpopquati8', '--quiet', 'pycparser']' returned non-zero exit status 1.

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-3cwd09rc/cairocffi/setup.py", line 13, in <module>
        'cairocffi/ffi_build.py:ffi_pixbuf']
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/__init__.py", line 144, in setup
        _install_setup_requires(attrs)
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/__init__.py", line 139, in _install_setup_requires
        dist.fetch_build_eggs(dist.setup_requires)
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/dist.py", line 721, in fetch_build_eggs
        replace_conflicting=True,
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/pkg_resources/__init__.py", line 783, in resolve
        replace_conflicting=replace_conflicting
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1066, in best_match
        return self.obtain(req, installer)
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/pkg_resources/__init__.py", line 1078, in obtain
        return installer(requirement)
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/dist.py", line 777, in fetch_build_egg
        return fetch_build_egg(self, req)
      File "/home/xxxx/Python/env36/lib/python3.6/site-packages/setuptools/installer.py", line 130, in fetch_build_egg
        raise DistutilsError(str(e))
    distutils.errors.DistutilsError: Command '['/home/xxxx/Python/env36/bin/python', '-m', 'pip', '--disable-pip-version-check', 'wheel', '--no-deps', '-w', '/tmp/tmpopquati8', '--quiet', 'pycparser']' returned non-zero exit status 1.
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

BTW: Where are the logs I'm supposed to check for the full command output?

liZe commented 4 years ago

... for Ubuntu Focal.

Better late than never!

Updating pip and setuptools isn't mandatory, of course. In fact: With outdated pip-9.0.1 setuptools-39.0.1 the WeasyPrint installation succeeds (though there are those 2 red scary lines you mentioned). The upgraded pip-20.0.2 setuptools-45.1.0 fails!

I’m so mad at Python packaging.

Really.

Could anyone on Earth explain why pip install weasyprint doesn’t work, and why pip install pycparser; pip install weasyprint does?

Could anyone on Earth explain why searching "invalid command 'bdist_wheel'" on your favorite search engine will return dozens similar problems and dozens of "just install wheel before" answers?

Hello, it’s 2020! Python is so powerful that it can help scientists to draw black holes, so sad it BREAKS DISTRIBUTION of PURE PYTHON PACKAGES each time PIP OR SETUPTOOLS IS UPDATED because someone created a PEP THAT HAS BEEN ACCEPTED that introduces yet another pyproject.toml (toml!) CONFIGURATION FILE I’LL PUT NEXT TO MANIFEST.in, setup.py, setup.cfg, tox.ini and requirements.txt.

More than 1000 open issues for setuptools and pip.

I know that the PyPA team members are doing their best. I’m really sorry to be so angry, I shouldn’t.

Dealing with legacy problems is hard. No hard feelings.

But…

Users gave up, they’ve just all turned into monkeys repeating "pip install wheel, don’t ask why, that’s what Stack Overflow said".

:monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face: :monkey_face:

Now, I’m a monkey too.

I don’t want to understand why pip (or setuptools, or whatever) needs to build wheels, and doesn’t fallback to the "legacy" code path for building and installing projects.

I give up. OK, we need to build wheels.

But, I’d love to find someone able to answer this question:

:sparkle: :sparkling_heart: :sparkle: Why does pip try to build a wheel without installing the wheel module first? :sparkle: :sparkling_heart: :sparkle:

(Oh, no! So sad! I’m pip, my job is to install packages, I need to build wheels, but the "wheel" package is not installed :cry:. If only I knew a way to install the "wheel" package… Wait!?!?)

(I’m ready to accept a pull request asking users to launch pip install --upgrade pip setuptools wheel before installing WeasyPrint.)

dcpc007 commented 4 years ago

If it can help, here my gitlab config for alpine image : pdf: image: python:alpine stage: final script:

hejsan commented 4 years ago

I'd like to add my pet peeve to this discussion.

Not everybody uses virtual environments for python packages. For dedicated servers running single webs/applications there is absolutely nothing wrong with installing system wide packages and in fact many organizations have "bare-metal" policies where any middle virtualization or obfuscation layers are frowned upon as they don't add value but do add complications to server configuration, dependencies and at worst cost cpu time. In fact the first thing mentioned after suggesting to add virtualenv instructions is that we need more dependencies.

If you want to use virtual environments you probably know how to translate the instructions to your preferred virtualenv - and they seem to come out with a new competing virtualenv implementation every quarter or so.

Also, I don't need every library I use to teach me how to use a virtual environment - but still way to many of them do. It's out of scope. If the installation instructions work on a server they also work inside your chosen virtualenv implementation, just without the sudo.

liZe commented 3 years ago

The documentation has been rewritten, including:

We close the issue now, but feel free to open new issues if you think that the new Linux documentation can be improved!