Virtualenv: Se excedió la longitud de Shebang en el ejecutable pip

Creado en 25 abr. 2014  ·  16Comentarios  ·  Fuente: pypa/virtualenv

Cuando se crea un nuevo virtualenv, hay una serie de cosas instaladas en ese virtualenv. Una de estas cosas es el instalador del paquete python, pip.

En Linux, el ejecutable pip es un script de shell. En la parte superior de este script de shell pip hay una línea shebang (#!) Que especifica el intérprete de Python en virtualenv. Esta línea contiene la ruta absoluta al intérprete de Python.

Si la ruta absoluta al intérprete de Python en virtualenv es muy larga (nombres de ruta grandes y / o profundamente anidados), puede exceder la longitud máxima permitida para una línea shebang.

La longitud máxima de una línea shebang está limitada en el kernel por BINPRM_BUF_SIZE, establecido en /usr/include/linux/binfmts.h. En las máquinas Linux que miré, este límite está establecido en 128.

Entonces, cuando la ruta, donde se crea un virtualenv de python, se vuelve demasiado larga, el uso del pip de ese virtualenv no funcionará. Fallará con el error: "mal intérprete: no existe tal archivo o directorio"

Una solución para este problema es no ejecutar pip directamente, sino ejecutar el intérprete de python de virtualenv y pasar el script pip a python como fuente para ejecutar.

Comentario más útil

Si alguien encuentra esto confuso:

Una solución para este problema es no ejecutar pip directamente, sino ejecutar el intérprete de python de virtualenv y pasar el script pip a python como fuente para ejecutar.

Eso significa que en lugar de pip install -r requirements.txt hacer python -m pip install -r requirements.txt

Todos 16 comentarios

También estoy experimentando este problema.

Yo también.

¡Gracias por la solución!

Tenga en cuenta que los scripts de contenedor en realidad son generados por setuptools (si instala desde sdist) o distlib (si instala desde wheel). Por lo tanto, cualquier solución para este problema debería solicitarse a esos proyectos.

Pero si se trata de una limitación del sistema operativo, ¿quizás simplemente no existe una solución viable? Creo recordar que en un momento, Perl usó un encantamiento mágico para ejecutar scripts (busca un poco en Google ...) Sí, algo como esto (traducido para Python)

#!/bin/sh
eval 'exec /the/long/interpreter/path/to/python $0 ${1+"$@"}'

Necesitaría algunas cosas adicionales para que Python no intente ejecutar la línea eval-exec, pero eso podría funcionar.

Si alguien quisiera proponer algo así como una solicitud de función para setuptools y distlib, sería genial.

Entonces, cuando la ruta, donde se crea un virtualenv de python, se vuelve demasiado larga, el uso del pip de ese virtualenv no funcionará.

Sería _realmente_ agradable si al ejecutar virtualenv en un sistema en el que ocurre este problema, el comando generaría alguna advertencia (o incluso un error) de que estar en un directorio con un nombre de ruta tan largo esencialmente no es compatible con los valores predeterminados en este momento.

También estoy golpeando esto. Es específicamente un problema para mí, ya que estoy ejecutando pip desde dentro de las compilaciones de Jenkins, que tienen rutas _muy_ largas hacia el pwd. Curiosamente, tengo varios esclavos de compilación construidos de manera idéntica (todos tienen BINPRM_BUF_SIZE configurado en 128, y las mismas versiones de pip y python y virtualenv) y estoy experimentando esto en algunos de ellos pero no en otros, incluso con diferentes longitudes de ruta.

Me gusta la sugerencia de @ b-long; si virtualenv va a crear una envoltura que no funciona en el sistema actual, al menos debería dar al usuario una advertencia, si no, fallará rotundamente.

No está claro cómo virtualenv pudo detectar esta situación. No podemos usar exactamente un valor de un encabezado C, y no sé cómo detectaríamos que estamos en un sistema con esta limitación (Windows no lo tiene, ¿verdad OSX?)

Me inclino a cerrar este problema como una limitación del sistema operativo, no como un problema virtualenv.

Por lo que vale, algunas reflexiones ...

  1. ¿Puede ctypes hacer esto?
  2. ¿Qué tal algo tan simple como:
# on Linux, BINPRM_BUF_SIZE == 128, giving us a maximum shebang length of 127
# 2 bytes for #!, 11 bytes for '/bin/python' leaves us with 114
if sys.platform() == 'Linux' and len(home_dir) > 114:
    log.warn("bin/activate may not work your system, as the length of the shebang line will exceed 128 characters")
  1. No tengo idea, lo siento.
  2. Soy un usuario de Windows, así que no tengo ninguna opinión. Si crees que esto es razonable, te sugiero que levantes un PR y veas lo que piensa la gente de Linux ...

Estoy seguro de que otros usuarios también agradecerían el cambio que sugerí. ¿Podemos dejar esto abierto para comentar e inspirar a un PR? Gracias @jantman y @pfmoore : smile:

BINPRM_BUF_SIZE se define en un encabezado del kernel y parece que solo lo utilizan un puñado de funciones del kernel. No creo que haya ninguna forma de detectar esto mediante programación (sin leer en los encabezados, lo que no es ni de lejos factible).

Una vez dicho esto, creo que es razonable suponer que esto no va a cambiar en el corto plazo (hay una visión rápida de la longitud máxima del tinglado aquí ). La longitud actual también se indica claramente en la sección "Notas" de la página de manual de execve (2) , donde dice: "Se permite una longitud máxima de línea de 127 caracteres para la primera línea en un script de shell ejecutable #!".

Asumiría que todos los sistemas operativos compatibles con POSIX tienen un límite de algún tipo, aunque parece que algunos de ellos, específicamente las variantes BSD, pueden tener límites de más de 8.000 caracteres.

Si bien parece que sería una solución razonable simplemente codificar algo tan ingenuo como mi sugerencia anterior (si la plataforma es Linux y la línea tiene más de 127 caracteres), me parece demasiado crudo, específico e inflexible.

Todavía estoy pensando en cómo probaría esto programáticamente de una manera que no agregaría demasiada sobrecarga a virtualenv (concedido, solo necesitaríamos probar esto en el momento de la creación de venv, así que ' Supongo que algunos gastos generales pueden ser aceptables).

Tengo un código de prueba de concepto simple para probar si una ruta dada tiene o no una longitud she-bang aceptable, pero es bastante feo ya que escribe un archivo en el disco y luego ejecuta el archivo para capturar la salida. El ejemplo y la salida están aquí: https://gist.github.com/jantman/ba39f98936643bc948bd

Voy a tener que dar por terminada la noche, pero intentaré volver a esto. Ciertamente agradecería la entrada de cualquier otro usuario de Linux, o usuarios de otros sistemas operativos que puedan confirmar si tienen o no un límite similar.

En lugar de intentar hacer algo complicado como hacer suposiciones sobre el límite, ¿por qué no simplemente hacer un script bash de prueba funcional? Si python se invoca correctamente, entonces todo es perfecto, de lo contrario no lo es.

Reiterar:

  1. Envíe los PR a setuptools y distlib si desea que esto se solucione; el código no está en virtualenv o pip.
  2. Para ser aceptable, el código debería funcionar en todas las plataformas compatibles, incluidas OSX, BSD, ... y no solo en Linux (los condicionales específicos de la plataforma son aceptables, por supuesto, si no hay otra forma)

Cerrando este problema, ya que no es un problema virtualenv (puede obtener el mismo efecto instalando un intérprete de Python completo en un nombre de directorio largo).

Acabamos de abordar este problema.

¿Por qué no usar Python del PATH? virtualenv ya lo antepone con el directorio bin.

#!/usr/bin/env python

virtualenv ya lo antepone con el directorio bin

Solo si activa virtualenv. Virtualenv admite el uso sin activación.

Si alguien encuentra esto confuso:

Una solución para este problema es no ejecutar pip directamente, sino ejecutar el intérprete de python de virtualenv y pasar el script pip a python como fuente para ejecutar.

Eso significa que en lugar de pip install -r requirements.txt hacer python -m pip install -r requirements.txt

¿Fue útil esta página
0 / 5 - 0 calificaciones