¿Debo poner #! (shebang) en los scripts de Python, y ¿qué forma debería tomar?

830

¿Debo poner el shebang en mis scripts de Python? En que forma

#!/usr/bin/env python 

o

#!/usr/local/bin/python

¿Son estos igualmente portátiles? ¿Qué forma se usa más?

Nota: elproyecto tornado usa el shebang. Por otro lado, elproyecto Django no.

codificador de árboles
fuente
70
El segundo no es portátil y se fallará en muchos equipos, si no la mayoría.
Dietrich Epp
44
¿Cómo se #!/usr/bin/pythoncompara con la primera opción? Veo esto en muchos códigos de ejemplo. Editar: Tal vez esta sea la respuesta ... stackoverflow.com/a/2429517/1156245
geotheory
1
Yo digo que siempre lo use, ¿por qué? "Zen of Python" - Línea 2 - "Explícito es mejor que implícito". python.org/dev/peps/pep-0020
JayRizzo
2
Francamente, ninguno de los dos es "correcto", porque usted, como autor, no sabe dónde estará la versión correcta de Python cuando se ejecute el script. Debería ser el trabajo del instalador agregar el shebang correcto.
chepner

Respuestas:

1117

La línea shebang en cualquier secuencia de comandos determina la capacidad de la secuencia de comandos para ejecutarse como un ejecutable independiente sin escribir de pythonantemano en el terminal o al hacer doble clic en un administrador de archivos (cuando está configurado correctamente). No es necesario, pero generalmente se coloca allí para que cuando alguien vea el archivo abierto en un editor, inmediatamente sepan lo que están viendo. Sin embargo, qué línea de shebang usas ES importante.

El uso correcto de los scripts de Python 3 es:

#!/usr/bin/env python3

Esto predeterminado a la versión 3.latest. Para Python 2.7. Uso posterior python2en lugar de python3.

Lo siguiente no se debe utilizar (excepto en el caso raro que usted está escribiendo código que es compatible tanto con Python 2.x y 3.x):

#!/usr/bin/env python

La razón de estas recomendaciones, dadas en PEP 394 , es que pythonpueden referirse a diferentes sistemas python2o python3en ellos. Actualmente se refiere a la python2mayoría de las distribuciones, pero es probable que eso cambie en algún momento.

Además, NO USE:

#!/usr/local/bin/python

"Python puede instalarse en / usr / bin / python o / bin / python en esos casos, el #! anterior fallará".

- "#! / usr / bin / env python" frente a "#! / usr / local / bin / python"

GlassGhost
fuente
44
@EliasVanOotegem Si no puede estar seguro de que se encontrará Python en, /usr/binentonces ¿cómo puede estar seguro de que envse encontrará en /usr/bin? Si python se instala en un lugar no estándar, es probable que python esté configurado de manera no estándar y que, como resultado, el script deba fallar rápidamente. En lugar de hacer suposiciones sobre las propiedades del intérprete de Python y esperar lo mejor.
Dunas
65
@Dunes: envserán siempre pueden encontrar en /usr/bin/, y su trabajo consiste en localizar los contenedores (como Python) usando PATH. No importa cómo esté instalado python, su ruta se agregará a esta variable y la envencontrará (si no, python no está instalado). Ese es el trabajo de env, esa es la razón por la cual existe. Es lo que alerta al entorno (configure las variables env, incluidas las rutas de instalación e incluya las rutas). La gente siempre ha entendido que este comando solo puede funcionar si siempre se encuentra en el mismo lugar. Eso es solo un hecho
Elias Van Ootegem
3
@JFSebastian: Tienes razón, no está garantizado ni se aplica por el estándar POSIX. Supuse que era porque una de las versiones posteriores de IEEE contenía algunas cosas del entorno. De cualquier manera: no, /usr/bin/envno está garantizado por ningún estándar, aparte de una regla ampliamente adoptada (¿universalmente?) ...
Elias Van Ootegem
66
Si está utilizando virtualenv, #! / Usr / local / bin / python, incluso si existe, se equivoca.
nullas
66
Un problema con esto: de acuerdo con PEP394, uno solo debe usar el pythonejecutable cuando el script es compatible con Python 2 y Python 3. De lo contrario, debe apuntar a la elección apropiada de python2y python3.
amiller27
67

Realmente es solo una cuestión de gustos. Agregar el shebang significa que las personas pueden invocar el script directamente si lo desean (suponiendo que esté marcado como ejecutable); omitirlo solo significa pythonque debe invocarse manualmente.

El resultado final de ejecutar el programa no se ve afectado de ninguna manera; son solo opciones de los medios.

Ámbar
fuente
3
Eso es todo: no importa qué lado tome porque no hay un lado "correcto". Es una decisión completamente subjetiva.
Ámbar
55
No más que cualquier otra decisión trivial. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber
2
¿Cómo podría ejecutar un archivo python directamente sin el comando 'python'?
Zen
55
@Zen Suponiendo que incluyó el shebang (#! / Usr / bin / env python) en su script, solo necesita hacer que su script sea ejecutable. Algo así chmod a+x [your-script].pydebería hacerlo ejecutable y luego puede llamar ./[your-script.py]a shell.
skålfyfan
99
Como la respuesta por GlassGhost señala, no es una ventaja concreta para incluirla además de sabor: se deja en claro que un lector futuro del archivo que se está leyendo un script ejecutable, en lugar de un archivo que está destinado a ser importado. De manera similar a los modificadores de control de acceso público / privado en los idiomas que los tienen, los shebangs son útiles como documentación , así como por su efecto real, y en algunos casos el aspecto de la documentación es realmente más importante.
Mark Amery
32

¿Debo poner el shebang en mis scripts de Python?

Pon un shebang en un script de Python para indicar:

  • este módulo puede ejecutarse como un script
  • si se puede ejecutar solo en python2, python3 o si es compatible con Python 2/3
  • en POSIX, es necesario si desea ejecutar el script directamente sin invocar el pythonejecutable explícitamente

¿Son estos igualmente portátiles? ¿Qué forma se usa más?

Si escribe un shebang manualmente, úselo siempre, a #!/usr/bin/env pythonmenos que tenga una razón específica para no usarlo. Este formulario se entiende incluso en Windows (Python Launcher).

Nota: los scripts instalados deben usar un ejecutable de Python específico, por ejemplo, /usr/bin/pythono /home/me/.virtualenvs/project/bin/python. Es malo si alguna herramienta se rompe si activa un virtualenv en su shell. Afortunadamente, el shebang correcto se crea automáticamente en la mayoría de los casos por las setuptoolsherramientas del paquete de distribución (en Windows, setuptoolspuede generar .exescripts de envoltura automáticamente).

En otras palabras, si el script está en un proceso de pago de origen, entonces probablemente verá #!/usr/bin/env python. Si está instalado, el shebang es una ruta a un ejecutable de Python específico como #!/usr/local/bin/python (NOTA: no debe escribir las rutas de la última categoría manualmente).

Para elegir si debe usar python, python2o python3en el shebang, consulte PEP 394 - El comando "python" en sistemas tipo Unix :

  • ... pythondebe usarse en la línea shebang solo para scripts que sean compatibles con fuentes tanto con Python 2 como con 3.

  • En preparación para un eventual cambio en la versión predeterminada de Python, los scripts de Python 2 solo deben actualizarse para que sean compatibles con Python 3 o bien para usar python2en la línea shebang.

jfs
fuente
3
La primera respuesta para referirse incluso a una PEP no tiene suficientes votos a favor. ¿Eh? ¿Hay una PEP para #!/usr/bin/env pythonsí misma?
binki
Por favor no lo use #!/usr/bin/env python. Por favor no sugiera "usar siempre" #!/usr/bin/env python. Esto es incorrecto en el 99% de los casos (la razón que ha incluido en su respuesta).
Jay Sullivan el
1
@ JaySullivan, ¿comprende la diferencia entre un pago de origen y los scripts instalados? Estoy detrás de la sugerencia. Funciona bien.
jfs
1
@jfs: Después de volver a leer mi comentario, veo cómo no pude expresar mi punto de vista. Lo que quise decir es que la mayoría de la gente querrá usar 'python2' o 'python3', no 'python'. Ya sea que se resuelva o no a través de la ruta completa o env, que técnicamente era la pregunta OP, usted respondió y no estoy en desacuerdo sobre ese punto.
Jay Sullivan
@ JaySullivan Estoy de acuerdo. ¿Leíste la cita del pep en la respuesta? Dice lo mismo.
jfs
15

Si tiene más de una versión de Python y el script necesita ejecutarse bajo una versión específica, she-bang puede garantizar que se use el correcto cuando el script se ejecuta directamente, por ejemplo:

#!/usr/bin/python2.7

Tenga en cuenta que el script aún se puede ejecutar a través de una línea de comando completa de Python, o mediante importación, en cuyo caso se ignora el she-bang. Pero para los scripts ejecutados directamente, esta es una razón decente para usar she-bang.

#!/usr/bin/env python generalmente es el mejor enfoque, pero esto ayuda con casos especiales.

Por lo general, sería mejor establecer un entorno virtual de Python, en cuyo caso el genérico #!/usr/bin/env pythonidentificaría la instancia correcta de Python para virtualenv.

Chris Johnson
fuente
¿No va a hacer que el espacio falle?
RandomInsano
1
@RandomInsano, no lo creo. Los espacios parecen bastante comunes y hay mucha evidencia en la red de esto como un uso aceptado. Sin embargo, creo que sin espacio es probablemente el uso más canónico.
Chris Johnson
1
Definitivamente tienes razón en este caso. Acabo de probar en bash y tcsh.
RandomInsano
Los resultados de whichle darán una cadena que funcionará, punto. No necesita preocuparse por ninguno de los intestinos para usarlo.
SDsolar
10

Debe agregar un shebang si el script está destinado a ser ejecutable. También debe instalar el script con un software de instalación que modifique el shebang a algo correcto para que funcione en la plataforma de destino. Ejemplos de esto son distutils y Distribute.

Lennart Regebro
fuente
1
¡No tiene que modificar el #! línea después. Para eso es / usr / bin / env. La codificación dura contra un intérprete de Python específico puede hacer más daño que bien. Es muy frágil con respecto a la instalación de otra versión de Python o cambiar entre nuestra distribución de Python versus una instalación personalizada de Python.
vog
En Ubuntu, el uso de los resultados de whichseleccionará automáticamente el valor predeterminado que utilizan los comandos del sistema y demás. Es genérico y el sistema lo dirige a la instalación adecuada.
SDsolar
9

El propósito de shebang es que el script reconozca el tipo de intérprete cuando desea ejecutar el script desde el shell. Principalmente, y no siempre, ejecuta scripts al proporcionar el intérprete externamente. Ejemplo de uso:python-x.x script.py

Esto funcionará incluso si no tienes un declarador shebang.

Por qué el primero es más "portátil" es porque /usr/bin/envcontiene su PATHdeclaración que explica todos los destinos donde residen los ejecutables de su sistema.

NOTA: Tornado no usa estrictamente shebangs, y Django estrictamente no lo hace. Varía según cómo esté ejecutando la función principal de su aplicación.

TAMBIÉN: No varía con Python.

meson10
fuente
8

A veces, si la respuesta no es muy clara (quiero decir que no puede decidir si sí o no), entonces no importa demasiado y puede ignorar el problema hasta que la respuesta sea clara.

El #!único propósito es lanzar el script. Django carga las fuentes por sí solo y las usa. Nunca necesita decidir qué intérprete debe usarse. De esta manera, la #!realidad no tiene sentido aquí.

Generalmente, si es un módulo y no se puede usar como un script, no hay necesidad de usar el #!. Por otro lado, una fuente de módulo a menudo contiene if __name__ == '__main__': ...al menos algunas pruebas triviales de la funcionalidad. Entonces el #!tiene sentido de nuevo.

Una buena razón para usarlo #!es cuando usa los scripts Python 2 y Python 3: deben ser interpretados por diferentes versiones de Python. De esta manera, debe recordar qué pythondebe usarse al iniciar el script manualmente (sin el #!interior). Si tiene una mezcla de tales scripts, es una buena idea usar el #!interior, hacerlos ejecutables y ejecutarlos como ejecutables (chmod ...).

Al usar MS-Windows, #!no tenía sentido, hasta hace poco. Python 3.3 presenta un Lanzador de Python de Windows (py.exe y pyw.exe) que lee la #!línea, detecta las versiones instaladas de Python y usa la versión correcta o explícitamente deseada de Python. Como la extensión se puede asociar con un programa, puede obtener un comportamiento similar en Windows como con el indicador de ejecución en sistemas basados ​​en Unix.

pepr
fuente
3

Cuando instalé Python 3.6.1 en Windows 7 recientemente, también instalé Python Launcher para Windows, que se supone que maneja la línea shebang. Sin embargo, descubrí que Python Launcher no hizo esto: la línea shebang fue ignorada y Python 2.7.13 siempre se usó (a menos que ejecute el script usando py -3).

Para solucionar esto, tuve que editar la clave de registro de Windows HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Esto todavía tenía el valor

"C:\Python27\python.exe" "%1" %*

de mi instalación anterior de Python 2.7. Modifiqué este valor de clave de registro a

"C:\Windows\py.exe" "%1" %*

y el procesamiento de la línea shebang de Python Launcher funcionó como se describió anteriormente.

ETalbot
fuente
2

Si tiene diferentes módulos instalados y necesita usar una instalación específica de Python, entonces shebang parece estar limitado al principio. Sin embargo, puede hacer trucos como el siguiente para permitir que se invoque el shebang primero como un script de shell y luego elija python. Esto es muy flexible:

#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    echo Using preferred python $PREFERRED_PYTHON
    exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())

O mejor aún, tal vez, para facilitar la reutilización del código en múltiples scripts de Python:

#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[@]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$@"; exit 127; '''

y luego select.sh tiene:

PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
    CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
    CHOSEN_PYTHON=$FALLBACK_PYTHON
fi
Neil McGill
fuente
1
Si bien no estoy seguro de que un políglota como este sea una buena práctica en general, sin duda es un enfoque muy interesante y probablemente la respuesta más flexible aquí.
Ryan Amos
1
Muy genial. No me di cuenta de que podrías hacer eso
user2233949
1

Respuesta: Solo si planea convertirlo en un script ejecutable de línea de comandos.

Aquí está el procedimiento:

Comience verificando la cadena shebang adecuada para usar:

which python

Tome el resultado de eso y agréguelo (con el shebang #!) En la primera línea.

En mi sistema responde así:

$which python
/usr/bin/python

Entonces su shebang se verá así:

#!/usr/bin/python

Después de guardar, seguirá ejecutándose como antes, ya que Python verá esa primera línea como un comentario.

python filename.py

Para convertirlo en un comando, cópielo para soltar la extensión .py.

cp filename.py filename

Dígale al sistema de archivos que esto será ejecutable:

chmod +x filename

Para probarlo, use:

./filename

La mejor práctica es moverlo a algún lugar de su $ PATH, por lo que todo lo que necesita escribir es el nombre del archivo.

sudo cp filename /usr/sbin

De esa manera funcionará en todas partes (sin el ./ antes del nombre del archivo)

SDsolar
fuente
Dudo que esta sea la mejor práctica y recomiendo utilizar la solución GlassGhost .
colidyre
Encontré esto útil y funcionó muy bien para mí. Esto fue bien explicado. Sin embargo, agradecería los comentarios que indiquen por qué esta no es una mejor práctica. Estoy ansioso por aprender
Charles Carriere
0

Ruta absoluta vs lógica:

Esta es realmente una pregunta sobre si la ruta al intérprete de Python debe ser absoluta o lógica ( /usr/bin/env) con respecto a la portabilidad.

Al encontrar otras respuestas en este y otros sitios de Stack que hablaron sobre el tema de manera general sin pruebas de apoyo, realicé algunas pruebas y análisis realmente, REALMENTE , granulares sobre esta misma pregunta en unix.stackexchange.com . En lugar de pegar esa respuesta aquí, señalaré a los interesados ​​en el análisis comparativo a esa respuesta:

https://unix.stackexchange.com/a/566019/334294

Como ingeniero de Linux, mi objetivo siempre es proporcionar los hosts más adecuados y optimizados para mis clientes desarrolladores, por lo que el problema de los entornos Python era algo para lo que realmente necesitaba una respuesta sólida. Mi opinión después de la prueba fue que la ruta lógica en el she-bang era la mejor de las (2) opciones.

F1Linux
fuente
-3

Usar primero

which python

Esto dará el resultado como la ubicación donde está presente mi intérprete de Python (binario).

Esta salida podría ser cualquiera como

/usr/bin/python

o

/bin/python

Ahora seleccione apropiadamente la línea shebang y úsela.

Para generalizar podemos usar:

#!/usr/bin/env

o

#!/bin/env
frp farhan
fuente
3
Lo más probable es que esto no sea portátil a otros sistemas. #!/usr/bin/envtoma la decisión correcta para ti.
fragmentedreality
Es por eso que usa el whichcomando: devolverá la cadena correcta para su sistema en particular.
SDsolar
1
... y luego cada vez que el guión se va a ejecutar en otra máquina, se ejecuta which pythonde nuevo y cambia la secuencia de comandos si los difiere de salida de la corriente tinglado
fragmentedreality
2
-1 Esta es la solución más frágil posible. Solo se garantiza que sea correcto para el sistema en el que está escrito su script de Python. Use #! / Usr / bin / env python3 para la portabilidad
Myles Hollowed