Dois-je mettre #! (shebang) dans les scripts Python, et quelle forme cela devrait-il prendre?

830

Dois-je mettre le shebang dans mes scripts Python? Sous quelle forme?

#!/usr/bin/env python 

ou

#!/usr/local/bin/python

Sont-ils également portables? Quelle forme est la plus utilisée?

Remarque: leprojet de tornade utilise le shebang. En revanche, leprojet Django ne le fait pas.

treecoder
la source
70
Le second est pas portable et va échouer sur de nombreux ordinateurs, sinon la plupart.
Dietrich Epp
4
Comment se #!/usr/bin/pythoncompare-t-il à la première option? Je vois cela dans beaucoup d'exemples de code. Edit: Peut-être que c'est la réponse .. stackoverflow.com/a/2429517/1156245
geotheory
1
Je dis toujours l'utiliser, pourquoi? "Zen Of Python" - Ligne 2 - "Explicite vaut mieux qu'implicite." python.org/dev/peps/pep-0020
JayRizzo
2
Franchement, ni l'un ni l'autre n'est "correct", car vous, en tant qu'auteur, ne savez pas où sera la bonne version de Python lorsque le script sera exécuté. Il devrait incomber à l' installateur d'ajouter le bon shebang.
chepner

Réponses:

1118

La ligne shebang dans n'importe quel script détermine la capacité du script à être exécuté comme un exécutable autonome sans avoir à taper pythonau préalable dans le terminal ou en double-cliquant dessus dans un gestionnaire de fichiers (lorsqu'il est configuré correctement). Ce n'est pas nécessaire, mais généralement mis là, donc quand quelqu'un voit le fichier ouvert dans un éditeur, il sait immédiatement ce qu'il regarde. Cependant, quelle ligne de shebang vous utilisez est importante.

L' utilisation correcte des scripts Python 3 est:

#!/usr/bin/env python3

Cette valeur par défaut est la version 3.latest. Pour Python 2.7.dernière utilisation python2à la place de python3.

Les éléments suivants ne doivent PAS être utilisés (sauf dans les rares cas où vous écrivez du code compatible avec Python 2.x et 3.x):

#!/usr/bin/env python

La raison de ces recommandations, données dans le PEP 394 , est qu'elles pythonpeuvent se référer à python2ou python3sur différents systèmes. Il fait actuellement référence à la python2plupart des distributions, mais cela est susceptible de changer à un moment donné.

N'utilisez PAS non plus:

#!/usr/local/bin/python

"python peut être installé dans / usr / bin / python ou / bin / python dans ces cas, le #! ci-dessus échouera."

- "#! / usr / bin / env python" vs "#! / usr / local / bin / python"

GlassGhost
la source
4
@EliasVanOotegem Si vous ne pouvez pas être certain que python sera trouvé, /usr/binalors comment pouvez-vous être certain qu'il envsera trouvé dans /usr/bin. Si python est installé dans un emplacement non standard, cela signifie probablement que python est configuré de manière non standard et que le script devrait en conséquence échouer rapidement. Par opposition à faire des hypothèses sur les propriétés de l'interpréteur python et à espérer le meilleur.
Dunes
65
@Dunes: envsera toujours trouvé dans /usr/bin/, et son travail consiste à localiser les bacs (comme python) à l'aide PATH. Peu importe la façon dont python est installé, son chemin sera ajouté à cette variable et envle trouvera (sinon, python n'est pas installé). C'est le travail de env, c'est la raison pour laquelle cela existe. C'est la chose qui alerte l'environnement (configurez les variables env, y compris les chemins d'installation et incluez les chemins). Les gens ont toujours compris que cette commande ne peut fonctionner que si elle se trouve toujours au même endroit. C'est juste une
évidence
3
@JFSebastian: Vous avez raison, ce n'est pas garanti ou appliqué par la norme POSIX. J'ai supposé que c'était parce que l'une des dernières versions de l'IEEE contenait des éléments d'environnement. Quoi qu'il en soit: non, /usr/bin/envn'est garanti par aucune norme, à part une règle largement (universellement?) Adoptée ...
Elias Van Ootegem
6
Si vous utilisez virtualenv, #! / Usr / local / bin / python, même s'il existe, se trompe.
null
6
Un problème avec ceci: selon PEP394, on ne devrait utiliser l' pythonexécutable que lorsque le script est compatible avec Python 2 et Python 3. Sinon, il devrait pointer vers le choix approprié parmi python2et python3.
amiller27
67

C'est vraiment juste une question de goût. L'ajout du shebang signifie que les gens peuvent invoquer le script directement s'ils le souhaitent (en supposant qu'il est marqué comme exécutable); son omission signifie simplement qu'elle pythondoit être invoquée manuellement.

Le résultat final de l'exécution du programme n'est pas affecté de toute façon; ce ne sont que des options de moyens.

ambre
la source
3
C'est juste ça - peu importe le côté que vous prenez parce qu'il n'y a pas de "bon" côté. C'est une décision complètement subjective.
Amber
5
Pas plus que toute autre décision banale. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber
2
Comment pourrais-je exécuter un fichier python directement sans la commande 'python'?
Zen
5
@Zen En supposant que vous avez inclus le shebang (#! / Usr / bin / env python) dans votre script, il vous suffit de rendre votre script exécutable. Quelque chose comme ça chmod a+x [your-script].pydevrait le rendre exécutable et ensuite vous pouvez simplement appeler ./[your-script.py]en shell.
skålfyfan
9
Comme le souligne la réponse de GlassGhost, il y a un avantage concret à l'inclure en plus du goût: il est clair pour un futur lecteur du fichier qu'il lit un script exécutable, plutôt qu'un fichier destiné à être importé. De la même manière que les modificateurs de contrôle d'accès public / privé dans les langues qui en disposent, les shebangs sont utiles comme documentation ainsi que pour leur effet réel, et dans certains cas, l'aspect documentation est le plus important.
Mark Amery
32

Dois-je mettre le shebang dans mes scripts Python?

Mettez un shebang dans un script Python pour indiquer:

  • ce module peut être exécuté comme un script
  • s'il peut être exécuté uniquement sur python2, python3 ou s'il est compatible avec Python 2/3
  • sur POSIX, il est nécessaire si vous souhaitez exécuter le script directement sans invoquer pythonexplicitement l'exécutable

Sont-ils également portables? Quelle forme est la plus utilisée?

Si vous écrivez un shebang manuellement, utilisez toujours #!/usr/bin/env pythonsauf si vous avez une raison spécifique de ne pas l'utiliser. Cette forme est comprise même sous Windows (lanceur Python).

Remarque: les scripts installés doivent utiliser un exécutable python spécifique, par exemple, /usr/bin/pythonou /home/me/.virtualenvs/project/bin/python. C'est mauvais si un outil se casse si vous activez un virtualenv dans votre shell. Heureusement, le shebang correct est créé automatiquement dans la plupart des cas par setuptoolsou vos outils de package de distribution (sous Windows, setuptoolspeuvent générer .exeautomatiquement des scripts wrapper ).

En d'autres termes, si le script est dans une extraction de source, vous le verrez probablement #!/usr/bin/env python. S'il est installé, le shebang est un chemin vers un exécutable python spécifique tel que #!/usr/local/bin/python (REMARQUE: vous ne devez pas écrire les chemins de cette dernière catégorie manuellement).

Pour choisir si vous devez utiliser python, python2ou python3dans le shebang, voir PEP 394 - La commande "python" sur les systèmes de type Unix :

  • ... pythondoit être utilisé dans la ligne shebang uniquement pour les scripts compatibles avec Python 2 et 3.

  • en prévision d'un éventuel changement dans la version par défaut de Python, seuls les scripts Python 2 doivent être mis à jour pour être compatibles avec Python 3 ou pour être utilisés python2dans la ligne shebang.

jfs
la source
3
La première réponse pour se référer même à un PEP n'a pas assez de votes positifs. Hein? Existe-t-il un PEP pour #!/usr/bin/env pythonlui-même?
binki
Veuillez ne pas utiliser #!/usr/bin/env python. Veuillez ne pas suggérer de "toujours utiliser" #!/usr/bin/env python. Ce n'est pas la bonne chose à faire dans 99% des cas (la raison que vous avez indiquée dans votre réponse).
Jay Sullivan
1
@JaySullivan comprenez-vous la différence entre une extraction de source et des scripts installés? Je soutiens la suggestion. Ça marche bien.
jfs
1
@jfs: Après avoir relu mon commentaire, je vois comment j'ai complètement échoué à faire passer mon message. Ce que je voulais dire, c'est que la plupart des gens voudront utiliser 'python2' ou 'python3', pas 'python'. Que ce soit pour résoudre via chemin complet ou env, qui était techniquement la question OP, vous avez répondu et je ne suis pas en désaccord sur ce point.
Jay Sullivan
@JaySullivan Je suis d'accord. Avez-vous lu la citation du pep dans la réponse. Cela dit la même chose.
jfs
15

Si vous avez plus d'une version de Python et que le script doit s'exécuter sous une version spécifique, la she-bang peut garantir que la bonne est utilisée lorsque le script est exécuté directement, par exemple:

#!/usr/bin/python2.7

Notez que le script peut toujours être exécuté via une ligne de commande Python complète, ou via l'importation, auquel cas le she-bang est ignoré. Mais pour les scripts exécutés directement, c'est une raison décente d'utiliser le she-bang.

#!/usr/bin/env python est généralement la meilleure approche, mais cela aide dans des cas particuliers.

Habituellement, il serait préférable d'établir un environnement virtuel Python, auquel cas le générique #!/usr/bin/env pythonidentifierait l'instance correcte de Python pour virtualenv.

Chris Johnson
la source
L'espace ne va-t-il pas le faire échouer?
RandomInsano
1
@RandomInsano, je ne pense pas. Les espaces semblent assez communs et il y a beaucoup de preuves autour du net comme utilisation acceptée. Cependant, je pense que le non-espace est probablement l'utilisation la plus canonique.
Chris Johnson
1
Vous avez définitivement raison sur celui-ci. Je viens de tester sur bash et tcsh.
RandomInsano
Les résultats de whichvous donneront une chaîne qui fonctionnera, point final. Vous n'avez pas à vous soucier des tripes pour l'utiliser.
SDsolar
10

Vous devez ajouter un shebang si le script est destiné à être exécutable. Vous devez également installer le script avec un logiciel d'installation qui modifie le shebang en quelque chose de correct afin qu'il fonctionne sur la plate-forme cible. Distutils et Distribute en sont des exemples.

Lennart Regebro
la source
1
Vous n'avez pas besoin de modifier le #! ligne après. C'est à ça que sert / usr / bin / env. Le codage en dur contre un interpréteur Python spécifique peut faire plus de mal que de bien. Il est très fragile d'installer une autre version de Python ou de basculer entre le Python de notre distribution et une installation Python personnalisée.
VOG
Dans Ubuntu, l'utilisation des résultats de whichsélectionnera automatiquement la valeur par défaut utilisée par les commandes système et autres. Il est générique et le système le dirige vers l'installation appropriée.
SDsolar
9

Le but de shebang est que le script reconnaisse le type d'interpréteur lorsque vous souhaitez exécuter le script à partir du shell. Généralement et pas toujours, vous exécutez des scripts en fournissant l'interpréteur en externe. Exemple d'utilisation:python-x.x script.py

Cela fonctionnera même si vous n'avez pas de déclarant shebang.

Pourquoi le premier est plus "portable" parce qu'il /usr/bin/envcontient votre PATHdéclaration qui représente toutes les destinations où résident les exécutables de votre système.

REMARQUE: Tornado n'utilise pas strictement les shebangs, et Django ne le fait pas strictement. Cela varie selon la façon dont vous exécutez la fonction principale de votre application.

AUSSI: Cela ne varie pas avec Python.

meson10
la source
8

Parfois, si la réponse n'est pas très claire (je veux dire que vous ne pouvez pas décider si oui ou non), alors cela n'a pas trop d'importance et vous pouvez ignorer le problème jusqu'à ce que la réponse soit claire.

Le #!seul but est de lancer le script. Django charge les sources par lui-même et les utilise. Il n'a jamais besoin de décider quel interprète doit être utilisé. De cette façon, le #!fait n'a aucun sens ici.

En général, s'il s'agit d'un module et ne peut pas être utilisé comme script, il n'est pas nécessaire d'utiliser le #!. D'un autre côté, une source de module contient souvent if __name__ == '__main__': ...avec au moins quelques tests triviaux de la fonctionnalité. Ensuite, le #!sens à nouveau.

Une bonne raison d'utiliser #!est lorsque vous utilisez à la fois des scripts Python 2 et Python 3 - ils doivent être interprétés par différentes versions de Python. De cette façon, vous devez vous rappeler ce qui pythondoit être utilisé lors du lancement manuel du script (sans l' #!intérieur). Si vous avez un mélange de ces scripts, c'est une bonne idée d'utiliser l' #!intérieur, de les rendre exécutables et de les lancer en tant qu'exécutables (chmod ...).

Lors de l'utilisation de MS-Windows, cela #!n'avait aucun sens - jusqu'à récemment. Python 3.3 présente un lanceur Windows Python (py.exe et pyw.exe) qui lit la #!ligne, détecte les versions installées de Python et utilise la version correcte ou explicitement souhaitée de Python. Comme l'extension peut être associée à un programme, vous pouvez obtenir un comportement similaire dans Windows comme avec l'indicateur d'exécution dans les systèmes basés sur Unix.

pepr
la source
3

Lorsque j'ai installé Python 3.6.1 sur Windows 7 récemment, il a également installé le lanceur Python pour Windows, qui est censé gérer la ligne shebang. Cependant, j'ai trouvé que le lanceur Python ne faisait pas cela: la ligne shebang était ignorée et Python 2.7.13 était toujours utilisé (à moins que j'exécute le script en utilisant py -3).

Pour résoudre ce problème, j'ai dû modifier la clé de registre Windows HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Cela avait encore de la valeur

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

de ma précédente installation Python 2.7. J'ai modifié cette valeur de clé de registre en

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

et le traitement de ligne de shebang Python Launcher a fonctionné comme décrit ci-dessus.

ETalbot
la source
2

Si vous avez différents modules installés et devez utiliser une installation spécifique de python, alors shebang semble être limité au début. Cependant, vous pouvez faire des astuces comme ci-dessous pour permettre au shebang d'être appelé d'abord en tant que script shell, puis de choisir python. C'est imo très 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())

Ou mieux encore, peut-être, pour faciliter la réutilisation du code sur plusieurs scripts python:

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

puis select.sh a:

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
la source
1
Bien que je ne sois pas sûr qu'un polyglotte comme celui-ci soit une bonne pratique en général, c'est certainement une approche très intéressante, et probablement la réponse la plus flexible ici.
Ryan Amos
1
Très cool. Je ne savais pas que tu pouvais faire ça
user2233949
1

Réponse: uniquement si vous prévoyez d'en faire un script exécutable en ligne de commande.

Voici la procédure:

Commencez par vérifier la chaîne de shebang appropriée à utiliser:

which python

Prenez la sortie de cela et ajoutez-la (avec le shebang #!) Dans la première ligne.

Sur mon système, il répond comme suit:

$which python
/usr/bin/python

Votre shebang ressemblera donc à:

#!/usr/bin/python

Après l'enregistrement, il fonctionnera comme avant car python verra cette première ligne comme un commentaire.

python filename.py

Pour en faire une commande, copiez-la pour supprimer l'extension .py.

cp filename.py filename

Dites au système de fichiers que ce sera exécutable:

chmod +x filename

Pour le tester, utilisez:

./filename

La meilleure pratique consiste à le déplacer quelque part dans votre $ PATH afin que vous n'ayez qu'à taper le nom du fichier lui-même.

sudo cp filename /usr/sbin

De cette façon, cela fonctionnera partout (sans le ./ avant le nom de fichier)

SDsolar
la source
Je doute que ce soit la meilleure pratique et je recommande fortement d'utiliser la solution de GlassGhost .
colidyre
J'ai trouvé cela utile et cela a fonctionné à merveille pour moi. cela a été bien expliqué. J'apprécierais toutefois des commentaires indiquant pourquoi ce n'est pas une meilleure pratique. J'ai hâte d'apprendre.
Charles Carriere
0

Chemin absolu vs chemin logique:

C'est vraiment une question de savoir si le chemin vers l'interpréteur Python doit être absolu ou Logical ( /usr/bin/env) en ce qui concerne la portabilité.

Rencontrant d'autres réponses sur ce site et sur d'autres sites Stack qui ont parlé du problème de manière générale sans prendre en charge les preuves, j'ai effectué des tests et des analyses vraiment, vraiment , granulaires sur cette même question sur le unix.stackexchange.com . Plutôt que de coller cette réponse ici, je vais diriger les personnes intéressées par l'analyse comparative vers cette réponse:

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

En tant qu'ingénieur Linux, mon objectif est toujours de fournir les hôtes les plus adaptés et optimisés pour mes clients développeurs, donc la question des environnements Python était quelque chose pour laquelle j'avais vraiment besoin d'une réponse solide. Mon avis après le test était que le chemin logique de la transe était la meilleure des (2) options.

F1Linux
la source
-3

Utiliser d'abord

which python

Cela donnera la sortie comme l'emplacement où mon interprète python (binaire) est présent.

Cette sortie pourrait être telle que

/usr/bin/python

ou

/bin/python

Maintenant, sélectionnez correctement la ligne de shebang et utilisez-la.

Pour généraliser, nous pouvons utiliser:

#!/usr/bin/env

ou

#!/bin/env
frp farhan
la source
3
Ce ne sera probablement pas portable sur d'autres systèmes. #!/usr/bin/envfait le bon choix pour vous.
fragmentedreality
C'est pourquoi vous utilisez la whichcommande - elle renverra la chaîne correcte pour votre système particulier.
SDsolar
1
... et à chaque fois que le script doit être exécuté sur une autre machine, vous réexécutez which pythonet modifiez le script si la sortie diffère du shebang actuel
fragmentedreality
2
-1 C'est la solution la plus fragile possible. Il n'est garanti que pour le système sur lequel votre script python est écrit. Utilisez #! / Usr / bin / env python3 pour la portabilité
Myles Hollowed