En Python 3.5.1 pero no en 2.7.10, cuando invoco pip a través de un subproceso en un virtualenv, los scripts se crean con el shebang incorrecto y, por lo tanto, no se ejecutan:
$ cat > invoke.py
import sys
import subprocess
subprocess.Popen(sys.argv[1:]).wait()
$ rm -Rf env
$ python -m virtualenv --version
14.0.0
$ python --version
Python 3.5.1
$ python -m virtualenv env
Using base prefix '/Library/Frameworks/Python.framework/Versions/3.5'
New python executable in /Users/jaraco/Dropbox/code/public/aspen/env/bin/python3
Also creating executable in /Users/jaraco/Dropbox/code/public/aspen/env/bin/python
Installing setuptools, pip, wheel...done.
$ python invoke.py env/bin/pip install pytest
Collecting pytest
Using cached pytest-2.8.5-py2.py3-none-any.whl
Collecting py>=1.4.29 (from pytest)
Using cached py-1.4.31-py2.py3-none-any.whl
Installing collected packages: py, pytest
Successfully installed py-1.4.31 pytest-2.8.5
$ head -n 1 env/bin/py.test
#!/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
Uno esperaría que el script py.test tuviera un shebang con 'env' en él.
El uso de pyvenv en su lugar no está sujeto al problema. Eliminar la variable de entorno __PYVENV_LAUNCHER__
antes de iniciar el subproceso soluciona el problema, como se informa aquí . El problema se observó con 13.1.2 y 14.0.0.
¿Se espera este comportamiento? Si es así, ¿eliminar la variable de entorno es lo apropiado que debe hacer un proceso principal para solucionar el problema?
lo hace
$ env/bin/pip uninstall pytest
$ env/bin/pip install pytest
$ head -n 1 env/bin/py.test
¿Dar resultados iguales o diferentes?
Y la misma pregunta con
$ env/bin/python -m pip install pytest
?
Posiblemente una regresión de alguna manera en https://github.com/pypa/virtualenv/issues/322 / https://github.com/pypa/virtualenv/pull/541
En cuyo caso, ¿podría probar si
subprocess.Popen(sys.argv[1:], env={}).wait()
ayuda o no?
Hmm, había un código en pip / distlib para tal vez lidiar con esto, pero se comentó hace un año.
¿Dar resultados iguales o diferentes?
En ambos casos, la invocación de pip da como resultado un shebang adecuado:
$ env/bin/pip install pytest
Collecting pytest
Using cached pytest-2.8.5-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): py>=1.4.29 in ./env/lib/python3.5/site-packages (from pytest)
Installing collected packages: pytest
Successfully installed pytest-2.8.5
$ head -n 1 env/bin/py.test
#!/Users/jaraco/Dropbox/code/public/aspen/env/bin/python3
$ env/bin/pip uninstall -y pytest
Uninstalling pytest-2.8.5:
Successfully uninstalled pytest-2.8.5
$ env/bin/python -m pip install pytest
Collecting pytest
Using cached pytest-2.8.5-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): py>=1.4.29 in ./env/lib/python3.5/site-packages (from pytest)
Installing collected packages: pytest
Successfully installed pytest-2.8.5
$ head -n 1 env/bin/py.test
#!/Users/jaraco/Dropbox/code/public/aspen/env/bin/python
Además, invocar con un env vacío funciona:
$ cat invoke.py
import sys
import os
import subprocess
env = dict(os.environ)
env.pop('__PYVENV_LAUNCHER__')
env = {}
subprocess.Popen(sys.argv[1:], env=env).wait()
$ python -m virtualenv env
Using base prefix '/Library/Frameworks/Python.framework/Versions/3.5'
New python executable in /Users/jaraco/Dropbox/code/public/aspen/env/bin/python3
Also creating executable in /Users/jaraco/Dropbox/code/public/aspen/env/bin/python
Installing setuptools, pip, wheel...done.
$ python invoke.py env/bin/pip install pytest
Collecting pytest
Using cached pytest-2.8.5-py2.py3-none-any.whl
Collecting py>=1.4.29 (from pytest)
Using cached py-1.4.31-py2.py3-none-any.whl
Installing collected packages: py, pytest
Successfully installed py-1.4.31 pytest-2.8.5
$ head -n 1 env/bin/py.test
#!/Users/jaraco/Dropbox/code/public/aspen/env/bin/python3
Según el compromiso , esa solución se comentó con la inclusión de distlib 0.2.0 lanzado en pip 6.0.
Ese compromiso hace referencia al pip 2031 .
Además, instalé Python desde el instalador de Python.org para Mac, no a través de homebrew u otros métodos.
El código se eliminó de distlib en esta confirmación , lo que proporciona pocas razones para el cambio.
Supongo que es "esperado" dado que su $ python
inicial está configurando __VENV_LAUNCHER__
y luego engañando a otros scripts / ejecutables. Desafortunadamente, no tengo OS X para depurar cómo se desarrolla exactamente ese proceso de "engañar".
También podría ser un problema similar o el mismo que se informó en el n. ° 620
@jaraco , podría valer la pena modificar un pip
en un virtualenv para descomentar las líneas distlib mencionadas y ver si eso parece arreglar el comportamiento de pip de elegir el pitón incorrecto para escribir
Rastreé ese código de detección de venv hasta este compromiso , que desafortunadamente no aclara los orígenes de la idea.
Parece que nadie conoce el significado de esta env var .
Encontré esta explicación .
Mi inclinación fue similar a lo que sugirió Ronald aquí .
@vsajip, ¿ podrías dar algún consejo?
Algunos pensamientos:
__PYVENV_LAUNCHER__
porque para las versiones anteriores de Python (<3.3, según Ronald) pero no para las versiones posteriores, el site.py
Python en OS X necesitaba distinguir la ubicación de los lanzadores de stub de los ejecutables del marco. Según este comentario de Ned Deily, sys.executable
ahora apunta al lanzador de stub, y esta es la razón por la que distlib
dejó de usar __PYVENV_LAUNCHER__
. El único uso de él ahora es en site.py
; si está disponible, en OS X, se usa para ubicar el archivo pyvenv.cfg
.os.path.realpath()
cuando no debería ser. No parece que sea distlib
haciendo eso. Si (según el comentario de Ned) sys.executable
y la var env son siempre iguales, entonces no debería importar; pero si algo hace un realpath
en un sys.executable
y ejecuta Python a través del resultado, entonces eso daría como resultado un shebang inesperado (porque sys.executable
sería entonces una ruta desreferenciada).Una (otra) demostración simple del problema, que Homebrew redescubrió en https://github.com/Homebrew/homebrew-core/pull/8129 :
$ virtualenv -p python3 test
$ test/bin/python3 -c 'import sys; print(sys.executable)'
/Users/tim/test/bin/python3
$ /usr/local/bin/python3 -c 'import subprocess; subprocess.call(["/Users/tim/test/bin/python3", "-c", "import sys; print(sys.executable)"])'
/usr/local/bin/python3
$ /usr/local/bin/python3 -c 'import subprocess, os; del os.environ["__PYVENV_LAUNCHER__"]; subprocess.call(["/Users/tim/test/bin/python3", "-c", "import sys; print(sys.executable)"])'
/Users/tim/test/bin/python3
Me acaba de picar este error exacto. En mi opinión, es un error bastante severo, principalmente porque es extremadamente confuso y difícil de averiguar cuándo ocurre.
Me ha afectado lo que creo que es una manifestación más grave de este problema.
Empecé a usar xonsh como mi caparazón diario.
Pero cuando trato de usar virtualenv bajo xonsh, es inutilizable:
~ $ cd ~/draft
draft $ virtualenv --version
16.0.0
draft $ virtualenv .env
Using base prefix '/Library/Frameworks/Python.framework/Versions/3.7'
New python executable in /Users/jaraco/draft/.env/bin/python3
Also creating executable in /Users/jaraco/draft/.env/bin/python
Installing setuptools, pip, wheel...done.
draft $ .env/bin/pip install paver
Collecting paver
Using cached https://files.pythonhosted.org/packages/98/1e/37ba8a75bd77ea56a75ef5ae66fe657b79205bbc36556c9456cd641782a4/Paver-1.3.4-py2.py3-none-any.whl
Collecting six (from paver)
Using cached https://files.pythonhosted.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl
Installing collected packages: six, paver
Successfully installed paver-1.3.4 six-1.11.0
The script paver is installed in '/Users/jaraco/draft/.env/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
draft $ .env/bin/paver --help
Traceback (most recent call last):
File ".env/bin/paver", line 7, in <module>
from paver.tasks import main
ModuleNotFoundError: No module named 'paver'
draft $ head -n 1 .env/bin/paver
#!/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
Todos los scripts instalados parecen tener el prefijo del sistema y no el prefijo virtualenv.
Esto probablemente se deba al hecho de que xonsh se ejecuta bajo Python 3.7 (prefijo del sistema) y también lo tiene en el entorno:
draft $ env | grep LAUNCHER
__PYVENV_LAUNCHER__=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
Si, en cambio, ejecuto zsh y ejecuto los mismos comandos o si primero invoco del $__PYVENV_LAUNCHER__
, la pavimentadora se ejecuta como se esperaba y la línea shebang apunta al virtualenv.
¿Debería xonsh borrar esa variable de entorno cuando se inicia?
Existe una posible corrección de errores en https://github.com/python/cpython/pull/9516
Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Simplemente agregue un comentario si desea mantenerlo abierto. Gracias por sus aportaciones.
Sigo viendo este mismo comportamiento en Mojave con Python 3.7.6 (instalado a través de Homebrew).
¿Puedes consultar con la rama de reescritura?
@gaborbernat Intentar construir la rama rewrite
(fbdd782257d8eace7f5440a2b665f2ddb72e9db6) me da un error de compilación de python3 setup.py build
.
...src/virtualenv/__init__.py", line 3, in <module>
from .version import __version__
ModuleNotFoundError: No module named 'virtualenv.version'
que parece no estar relacionado con este problema.
Intentar construir la rama de reescritura (fbdd782) me da un error de compilación de python3 setup.py build.
Debe usar pip para hacer la compilación - pip wheel .
- ya que la rama de reescritura usa pyproject.toml
para definir el proceso de compilación.
El error que está recibiendo es la forma de setuptools de decir que no soy compatible con la nueva forma estándar de crear bibliotecas de Python (PEP-517/518). En el mejor de los casos, es un error de setuptools, pero como @pfmoore señaló, debería usar pip para construir una rueda, o mejor aún, apuntar a la carpeta virtualenv para instalarla (automáticamente construirá una rueda y la instalará de una vez).
Caso de prueba:
#!/bin/bash
rm -rf venv-test
virtualenv --python python3 venv-test
python3 -c 'import subprocess; subprocess.check_call(["./venv-test/bin/pip3", "install", "markdown"])'
shebang=$(head -1 venv-test/bin/markdown_py)
expected_shebang="#!$(pwd)/venv-test/bin/python"
if [ "$shebang" == "$expected_shebang" ]; then
echo "PASSED"
else
echo "FAILED: \"$shebang\" != \"$expected_shebang\""
exit 1
fi
Esto falla bajo python3 + virtualenv 16.7.9, y pasa bajo python3 + virtualenv-16.7.10.dev11 + gfbdd782 (es decir, la rama rewrite
).
Se corrigió en la reescritura como se indicó anteriormente.
Comentario más útil
Me acaba de picar este error exacto. En mi opinión, es un error bastante severo, principalmente porque es extremadamente confuso y difícil de averiguar cuándo ocurre.