Tengo un script de Python que se debe ejecutar con una instalación de Python en particular. ¿Hay alguna manera de crear un shebang para que funcione $FOO/bar/MyCustomPython
?
Tengo un script de Python que se debe ejecutar con una instalación de Python en particular. ¿Hay alguna manera de crear un shebang para que funcione $FOO/bar/MyCustomPython
?
Respuestas:
La línea shebang es muy limitada. En muchas variantes de Unix (incluido Linux), solo puede tener dos palabras: un comando y un único argumento. También a menudo hay una limitación de longitud.
La solución general es escribir un pequeño envoltorio de shell. Asigne un nombre al script de Python foo.py
, coloque el script de shell al lado foo.py
y llámelo foo
. Este enfoque no requiere ningún encabezado particular en el script de Python.
#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"
Otro enfoque tentador es escribir una secuencia de comandos de envoltura como la anterior y ponerla #!/path/to/wrapper/script
como la línea shebang en la secuencia de comandos de Python. Sin embargo, la mayoría de las unidades no admiten el encadenamiento de scripts shebang, por lo que esto no funcionará.
Si MyCustomPython
estaba en el $PATH
, podría usar env
para buscarlo:
#!/usr/bin/env MyCustomPython
import …
Otro enfoque es organizar que el script sea tanto un script de shell válido (que carga el intérprete de Python correcto en sí mismo) como un script válido en el lenguaje de destino (aquí Python). Esto requiere que encuentre una manera de escribir una secuencia de comandos de doble idioma para su idioma de destino. En Perl, esto se conoce como if $running_under_some_shell
.
#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
if $running_under_some_shell;
use …
Aquí hay una forma de lograr el mismo efecto en Python. En el shell, "true"
está la true
utilidad, que ignora sus argumentos (dos cadenas de un solo carácter :
y '
) y devuelve un valor verdadero. En Python, "true"
es una cadena que es verdadera cuando se interpreta como un booleano, por lo que esta es una if
instrucción que siempre es verdadera y ejecuta un literal de cadena.
#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …
El código de Rosetta tiene dichos scripts en dos idiomas en varios otros idiomas.
PYTHONPATH
variable env para cargar módulos desde una ubicación no estándar para un script CGI en un sistema al que no tenía acceso root. Salvavidas Gracias de nuevo.
Las líneas Shebang no experimentan una expansión variable, por lo que no puede usar, $FOO/MyCustomPython
ya que buscaría un ejecutable llamado dollar-FOO -...
Una alternativa es hacer que su shebang apunte a un script de shell como intérprete, y este script de shell puede usar variables de entorno para localizar el correcto y ejecutarlo.
Ejemplo: cree un mypython.sh
script en /usr/local/bin
(o cualquier otro directorio en su $PATH
), con el siguiente contenido:
#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"
entonces puede usar esta línea shebang para ejecutar un script Python a MyCustomPython
través de mypython.sh
:
#!/usr/bin/env mypython.sh
$python
, no $PYTHON
- por convención, capitalizamos las variables de entorno (PAGER, EDITOR, SHELL ... $PYTHON
en su script no es una variable de entorno) y las variables de shell internas (BASH_VERSION, RANDOM, ...). Todos los demás nombres de variables deben contener al menos una letra minúscula. Esta convención evita anular accidentalmente variables ambientales e internas. Además, no use extensiones para sus scripts. Las secuencias de comandos definen nuevos comandos que puede ejecutar, y los comandos generalmente no tienen extensiones.
Puede usar la ruta absoluta a la instalación personalizada de Python, o puede ponerla en su $PATH
y usar #!/usr/bin/env [command]
. De lo contrario, escriba un contenedor para ello y úselo exec
para reemplazar la imagen del proceso, como ejemplo:
#!/bin/bash
exec "$ENV/python" "$@"
Primero, determine cómo su versión de Python es diferente de la versión estándar de Python ya instalada (por ejemplo, un módulo adicional) y luego, al inicio del programa, “cambie” cómo se llama a Python:
#!/usr/bin/python
import os
import sys
try:
import MyCustomModule
except ImportError:
# only need to use expandvar if you know the string below has an envvar
custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
os.execv(custprog, sys.argv) # call alternate python with the same arguments
raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter
Esto debería permitir que cualquier otra instancia de Python llame al programa. Hago algo similar para una instancia con la biblioteca sql incorporada que no se puede importar como módulo en la python del sistema.
Si se puede sustituir $FOO
en $FOO/bar/MyCustomPython
la opción de trazado de hormigón, se puede decir la env
línea de tinglado donde para buscar su versión personalizada de Python mediante el establecimiento de una costumbre directamente PATH
en ella.
#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python
Editar : parece funcionar solo sin comillas alrededor de la asignación del valor PATH:
#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
PATH
así:PATH=$PATH:/path/to/whatever...