virtualenv --always-copy fails on CentOS (lib64 problem?)

Created on 5 Mar 2019  ·  12Comments  ·  Source: pypa/virtualenv

Creating a virtualenv with --always-copy on a platform that uses /lib64 directory seems to be impossible.

On CentOS 7.6, the same happens both with the system packages (python 2.7.5, virtualenv 15.1.0) and the ones installed via SCL.
There are some tickets that may be related (#985, #1192, #3477, https://github.com/FPGAwars/icestudio/issues/244), and a merged pull request that supposedly fixes the problem (#1189), yet I have the impression that there is still something wrong happening.

Example using SCL (Python 3.6.3, virtualenv manually upgraded to 16.4.3).
The first error seems to happen in virtualenv_support/pip-19.0.3-py2.py3-none-any.whl:

  File "<scl_base>/lib64/python3.6/socket.py", line 49, in <module>
    import _socket
ModuleNotFoundError: No module named '_socket'

Complete log to see it in context.

$ <scl_base>/bin/virtualenv --python <scl_base>/bin/python --always-copy --verbose TEST
Running virtualenv with interpreter <scl_base>/bin/python
Using base prefix '<scl_base>'
Creating <somedir>/TEST/lib/python3.6
Copying to <somedir>/TEST/lib64
Symlinking Python bootstrap modules
  Copying to <somedir>/TEST/lib/python3.6/config-3.6m-x86_64-linux-gnu
  Copying to <somedir>/TEST/lib/python3.6/lib-dynload
  Copying to <somedir>/TEST/lib64/python3.6/os.py
  Ignoring built-in bootstrap module: posix
  Copying to <somedir>/TEST/lib64/python3.6/posixpath.py
  Cannot import bootstrap module: nt
  Copying to <somedir>/TEST/lib64/python3.6/ntpath.py
  Copying to <somedir>/TEST/lib64/python3.6/genericpath.py
  Copying to <somedir>/TEST/lib64/python3.6/fnmatch.py
  Copying to <somedir>/TEST/lib64/python3.6/locale.py
  Copying to <somedir>/TEST/lib64/python3.6/encodings
  Copying to <somedir>/TEST/lib64/python3.6/codecs.py
  Copying to <somedir>/TEST/lib64/python3.6/stat.py
  Cannot import bootstrap module: UserDict
  Creating parent directories for <somedir>/TEST/lib64/python3.6/lib-dynload
  Copying to <somedir>/TEST/lib64/python3.6/lib-dynload/readline.cpython-36m-x86_64-linux-gnu.so
  Cannot import bootstrap module: copy_reg
  Copying to <somedir>/TEST/lib64/python3.6/types.py
  Copying to <somedir>/TEST/lib64/python3.6/re.py
  Cannot import bootstrap module: sre
  Copying to <somedir>/TEST/lib64/python3.6/sre_parse.py
  Copying to <somedir>/TEST/lib64/python3.6/sre_constants.py
  Copying to <somedir>/TEST/lib64/python3.6/sre_compile.py
  Copying to <somedir>/TEST/lib64/python3.6/lib-dynload/zlib.cpython-36m-x86_64-linux-gnu.so
  Cannot import bootstrap module: _abcoll
  Copying to <somedir>/TEST/lib64/python3.6/warnings.py
  Copying to <somedir>/TEST/lib64/python3.6/linecache.py
  Copying to <somedir>/TEST/lib64/python3.6/abc.py
  Copying to <somedir>/TEST/lib64/python3.6/io.py
  Copying to <somedir>/TEST/lib64/python3.6/_weakrefset.py
  Copying to <somedir>/TEST/lib64/python3.6/copyreg.py
  Copying to <somedir>/TEST/lib64/python3.6/tempfile.py
  Copying to <somedir>/TEST/lib64/python3.6/random.py
  Copying to <somedir>/TEST/lib64/python3.6/__future__.py
  Copying to <somedir>/TEST/lib64/python3.6/collections
  Copying to <somedir>/TEST/lib64/python3.6/keyword.py
  Copying to <somedir>/TEST/lib64/python3.6/tarfile.py
  Copying to <somedir>/TEST/lib64/python3.6/shutil.py
  Copying to <somedir>/TEST/lib64/python3.6/struct.py
  Copying to <somedir>/TEST/lib64/python3.6/copy.py
  Copying to <somedir>/TEST/lib64/python3.6/tokenize.py
  Copying to <somedir>/TEST/lib64/python3.6/token.py
  Copying to <somedir>/TEST/lib64/python3.6/functools.py
  Copying to <somedir>/TEST/lib64/python3.6/heapq.py
  Copying to <somedir>/TEST/lib64/python3.6/bisect.py
  Copying to <somedir>/TEST/lib64/python3.6/weakref.py
  Copying to <somedir>/TEST/lib64/python3.6/reprlib.py
  Copying to <somedir>/TEST/lib64/python3.6/base64.py
  Copying to <somedir>/TEST/lib64/python3.6/_dummy_thread.py
  Copying to <somedir>/TEST/lib64/python3.6/hashlib.py
  Copying to <somedir>/TEST/lib64/python3.6/hmac.py
  Copying to <somedir>/TEST/lib64/python3.6/imp.py
  Copying to <somedir>/TEST/lib64/python3.6/importlib
  Copying to <somedir>/TEST/lib64/python3.6/rlcompleter.py
  Copying to <somedir>/TEST/lib64/python3.6/operator.py
  Copying to <somedir>/TEST/lib64/python3.6/_collections_abc.py
  Copying to <somedir>/TEST/lib64/python3.6/_bootlocale.py
  Copying to <somedir>/TEST/lib64/python3.6/enum.py
  No LICENSE.txt / LICENSE found in source
Creating <somedir>/TEST/lib/python3.6/site-packages
Writing <somedir>/TEST/lib64/python3.6/site.py
Writing <somedir>/TEST/lib64/python3.6/orig-prefix.txt
Writing <somedir>/TEST/lib64/python3.6/no-global-site-packages.txt
Creating <somedir>/TEST/bin
New python executable in <somedir>/TEST/bin/python
Changed mode of <somedir>/TEST/bin/python to 0o775
Copying to <somedir>/TEST/bin/python3
Copying to <somedir>/TEST/bin/python3.6
Testing executable with <somedir>/TEST/bin/python -c "import sys;out=sys.stdout;getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))"
Got sys.prefix result: '<somedir>/TEST'
Creating <somedir>/TEST/lib64/python3.6/distutils
Writing <somedir>/TEST/lib64/python3.6/distutils/__init__.py
Writing <somedir>/TEST/lib64/python3.6/distutils/distutils.cfg
Traceback (most recent call last):
  File "<scl_base>/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "<scl_base>/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl/pip/__main__.py", line 16, in <module>
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/__init__.py", line 19, in <module>
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl/pip/_vendor/urllib3/__init__.py", line 8, in <module>
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl/pip/_vendor/urllib3/connectionpool.py", line 7, in <module>
  File "<scl_base>/lib64/python3.6/socket.py", line 49, in <module>
    import _socket
ModuleNotFoundError: No module named '_socket'
Command <somedir>/TEST/bin/python -m pip config list had error code 1
Installing setuptools, pip, wheel...

  Traceback (most recent call last):
    File "<stdin>", line 4, in <module>
    File "<somedir>/TEST/lib64/python3.6/tempfile.py", line 45, in <module>
      from random import Random as _Random
    File "<somedir>/TEST/lib64/python3.6/random.py", line 42, in <module>
      from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
  ModuleNotFoundError: No module named 'math'
  Complete output from command <somedir>/TEST/bin/python - setuptools pip wheel:
  Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<somedir>/TEST/lib64/python3.6/tempfile.py", line 45, in <module>
    from random import Random as _Random
  File "<somedir>/TEST/lib64/python3.6/random.py", line 42, in <module>
    from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
ModuleNotFoundError: No module named 'math'
----------------------------------------
...Installing setuptools, pip, wheel...done.
Traceback (most recent call last):
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 2567, in <module>
    main()
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 793, in main
    symlink=options.symlink,
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 1088, in create_environment
    install_wheel(to_install, py_executable, search_dirs, download=download)
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 935, in install_wheel
    _install_wheel_with_search_dir(download, project_names, py_executable, search_dirs)
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 1025, in _install_wheel_with_search_dir
    call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=script)
  File "<scl_base>/usr/lib/python3.6/site-packages/virtualenv.py", line 886, in call_subprocess
    raise OSError("Command {} failed with error code {}".format(cmd_desc, proc.returncode))
OSError: Command <somedir>/TEST/bin/python - setuptools pip wheel failed with error code 1

I have really tried lots of combinations (many versions, playing with PATH and PYTHONPATH) with no luck. Any help appreciated.

bug

Most helpful comment

venv pip has this and outputs an error:

!"/mnt/c/Users/Artem Russakovskii/Dropbox/workspace/SNIP.test/SNIP/env-linux/bin/python3"

This is a ugly bug you found. From its looks, seems a missing quoting in some bash script (which would not surprise me, given how often this is overlooked).

I'll try to find it, since this kind of stuff scratch an itch for me. It won't solve your problem, but at least we'll get out with something good for someone.

All 12 comments

Hi, an info for future users, in case they need a fix before this bug is smashed.

Since my project is on python3, I sidestepped the poblem replacing:

virtualenv --always-copy

with

python -m venv --copies

This works on CentOS 7.x (no ModuleNotFoundError: No module named '_socket' and ModuleNotFoundError: No module named 'math'), and essentially moves away from virtualenv, which was a viable choice in my project anyway.

So the option name has changed?
IMO, (if the meaning is the same, at least) the (old) --always-copy long option should be supported as an alias for the (new) --copies option. This should not be difficult; it was no problem for optparse options, where the first long option string found was the one taken for the default dest.

Hi @tobiasherp, not exactly.

The two options refer to different programs: --always-copy is a virtualenv option, --copies is for python -m venv.

What I did is ditching virtualenv altogether, and use -m venv which, starting from python3, is available by default without needing to install anything, and works well for my case.

I see

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/tmp/tmp_6oib3xo/venv/lib64/python3.7/tempfile.py", line 45, in <module>
    from random import Random as _Random
  File "/tmp/tmp_6oib3xo/venv/lib64/python3.7/random.py", line 42, in <module>
    from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
ModuleNotFoundError: No module named 'math'

When i attempt to run tests/test_virtualenv.py::test_always_copy_option

I'm seeing the same issue on OpenSUSE 15.0 and 15.1.

virtualenv --always-copy temp
Using base prefix '/usr'
New python executable in /srv/www/htdocs/dev.SNIP.com/apk-downloader/temp/bin/python3
Also creating executable in /srv/www/htdocs/dev.SNIP.com/apk-downloader/temp/bin/python
Command /srv/www/htdocs/dev....der/temp/bin/python3 -m pip config list had error code 1
Installing setuptools, pip, wheel...

  Complete output from command /srv/www/htdocs/dev....der/temp/bin/python3 - setuptools pip wheel:
  Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/srv/www/htdocs/dev.SNIP.com/apk-downloader/temp/lib64/python3.6/tempfile.py", line 45, in <module>
    from random import Random as _Random
  File "/srv/www/htdocs/dev.SNIP.com/apk-downloader/temp/lib64/python3.6/random.py", line 42, in <module>
    from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
ModuleNotFoundError: No module named 'math'
----------------------------------------
...Installing setuptools, pip, wheel...done.
Traceback (most recent call last):
  File "/usr/bin/virtualenv", line 11, in <module>
    load_entry_point('virtualenv==16.7.5', 'console_scripts', 'virtualenv')()
  File "/usr/lib/python3.6/site-packages/virtualenv.py", line 870, in main
    symlink=options.symlink,
  File "/usr/lib/python3.6/site-packages/virtualenv.py", line 1173, in create_environment
    install_wheel(to_install, py_executable, search_dirs, download=download)
  File "/usr/lib/python3.6/site-packages/virtualenv.py", line 1019, in install_wheel
    _install_wheel_with_search_dir(download, project_names, py_executable, search_dirs)
  File "/usr/lib/python3.6/site-packages/virtualenv.py", line 1110, in _install_wheel_with_search_dir
    call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=script)
  File "/usr/lib/python3.6/site-packages/virtualenv.py", line 963, in call_subprocess
    raise OSError("Command {} failed with error code {}".format(cmd_desc, proc.returncode))
OSError: Command /srv/www/htdocs/dev....der/temp/bin/python3 - setuptools pip wheel failed with error code 1

@gaborbernat Any ideas here? Without --always-copy, it runs correctly.

I tried the venv workaround and found it still creates a symlink even when --copies is used. Why?

python3 -m venv --copies temp
SNIP@pylon:/srv/www/htdocs/dev.SNIP.com/apk-downloader> l temp
total 24
drwxr-xr-x 5 SNIP users 4096 Oct 30 14:09 ./
drwxr-xr-x 7 SNIP users 4096 Oct 30 14:09 ../
drwxr-xr-x 2 SNIP users 4096 Oct 30 14:09 bin/
drwxr-xr-x 2 SNIP users 4096 Oct 30 14:09 include/
drwxr-xr-x 3 SNIP users 4096 Oct 30 14:09 lib/
lrwxrwxrwx 1 SNIP users    3 Oct 30 14:09 lib64 -> lib/
-rw-r--r-- 1 SNIP users   69 Oct 30 14:09 pyvenv.cfg

@archon810, that's true: /lib64, with python -m venv --copies is still a symlink, but luckily that's the only one remaining: try running without --copies and have a look at the contents of /lib/pyhon3.6/site-packages: a lot of files will be symlinks.

I do not know if it's enough for your needs. For me the use case was making sure that a user did not inadvertently mess up file permission in other directories while operating on his virtualenv. In this case it s acceptable that /lib64 is a symlink, since it stays within the virtualenv directory structure.

Side note: with python3 having available venv by default, I stopped using virtualenv altogether anyway.

I'm trying to set up a Python env inside WSL on Windows, in a Dropbox folder, and Dropbox gets confused by any symlinks. This is the last set of symlinks left for me to figure out, and virtualenv was pretty much there, had it not had this math crash.

I mean, I could add an rm and cp -R to venv and try to go that route, but it'd be good if it actually did what it says it's doing and didn't have symlinks at all.

python3 -m venv --copies env-linux && rm env-linux/lib64 && cp -R env-linux/lib env-linux/lib64

Ughhh, turns out venv is no good because it doesn't handle dirs with spaces.

virtualenv pip has this and works:

#!/bin/sh
'''exec' "/mnt/c/Users/Artem Russakovskii/Dropbox/workspace/SNIP.test/SNIP/env-linux/bin/python3" "$0" "$@"
' '''

venv pip has this and outputs an error:

#!"/mnt/c/Users/Artem Russakovskii/Dropbox/workspace/SNIP.test/SNIP/env-linux/bin/python3"
bash: env-linux.new/bin/pip3: "/mnt/c/Users/Artem: bad interpreter: No such file or directory

Confirmed this math issue is present using the latest 16.7.7 version.

venv pip has this and outputs an error:

!"/mnt/c/Users/Artem Russakovskii/Dropbox/workspace/SNIP.test/SNIP/env-linux/bin/python3"

This is a ugly bug you found. From its looks, seems a missing quoting in some bash script (which would not surprise me, given how often this is overlooked).

I'll try to find it, since this kind of stuff scratch an itch for me. It won't solve your problem, but at least we'll get out with something good for someone.

https://github.com/pypa/virtualenv/pull/1500 should solve this now once and for all.

Was this page helpful?
0 / 5 - 0 ratings