Il me semble que les fichiers fonctionnent de la même manière sans cette ligne.
Il me semble que les fichiers fonctionnent de la même manière sans cette ligne.
Réponses:
Si vous avez plusieurs versions de Python installées, vous vous /usr/bin/env
assurerez que l'interpréteur utilisé est le premier sur votre environnement $PATH
. L'alternative serait de coder en dur quelque chose comme #!/usr/bin/python
; c'est ok, mais moins flexible.
Sous Unix, un fichier exécutable destiné à être interprété peut indiquer quel interpréteur utiliser en ayant un #!
au début de la première ligne, suivi de l'interpréteur (et de tous les indicateurs dont il peut avoir besoin).
Si vous parlez d'autres plates-formes, bien sûr, cette règle ne s'applique pas (mais cette "ligne shebang" ne fait aucun mal, et vous aidera si vous copiez jamais ce script sur une plate-forme avec une base Unix, telle que Linux, Mac , etc).
chmod +x myscript.py
) puis en l'exécutant directement:, ./myscript.py
plutôt que simplement python myscript.py
.
env
donne une flexibilité maximale dans la mesure où l'utilisateur peut sélectionner l'interpréteur à utiliser en changeant le CHEMIN. Souvent, cette flexibilité n'est cependant pas requise et l'inconvénient est que Linux par exemple ne peut pas utiliser le nom du script pour le nom du processus dans ps
et revient à "python". Lors du packaging d'applications python pour des distributions par exemple, je vous déconseille de les utiliser env
.
py
le lanceur peut utiliser la ligne shebang sous Windows. Il est inclus dans Python 3.3 ou il peut être installé indépendamment .
/usr/bin/env: Key has expired
après plusieurs heures.
C'est ce qu'on appelle la ligne shebang . Comme l' explique l'entrée Wikipedia :
En informatique, un shebang (également appelé hashbang, hashpling, pound bang ou crunchbang) fait référence aux caractères "#!" lorsqu'ils sont les deux premiers caractères d'une directive interpréteur comme première ligne d'un fichier texte. Dans un système d'exploitation de type Unix, le programme de chargement prend la présence de ces deux caractères comme une indication que le fichier est un script et essaie d'exécuter ce script à l'aide de l'interpréteur spécifié par le reste de la première ligne du fichier.
Voir aussi l' entrée FAQ Unix .
Même sous Windows, où la ligne shebang ne détermine pas l'interpréteur à exécuter, vous pouvez transmettre des options à l'interpréteur en les spécifiant sur la ligne shebang. Je trouve utile de conserver une ligne générique de shebang dans des scripts uniques (tels que ceux que j'écris lorsque je réponds à des questions sur SO), afin de pouvoir les tester rapidement sur Windows et ArchLinux .
L' utilitaire env vous permet d'appeler une commande sur le chemin:
Le premier argument restant spécifie le nom du programme à invoquer; il est recherché selon la
PATH
variable d'environnement. Tous les arguments restants sont passés comme arguments à ce programme.
Développant un peu les autres réponses, voici un petit exemple de la façon dont vos scripts de ligne de commande peuvent avoir des ennuis en utilisant /usr/bin/env
prudemment les lignes de shebang:
$ /usr/local/bin/python -V
Python 2.6.4
$ /usr/bin/python -V
Python 2.5.1
$ cat my_script.py
#!/usr/bin/env python
import json
print "hello, json"
$ PATH=/usr/local/bin:/usr/bin
$ ./my_script.py
hello, json
$ PATH=/usr/bin:/usr/local/bin
$ ./my_script.py
Traceback (most recent call last):
File "./my_script.py", line 2, in <module>
import json
ImportError: No module named json
Le module json n'existe pas dans Python 2.5.
Une façon de se prémunir contre ce type de problème consiste à utiliser les noms de commande python versionnés qui sont généralement installés avec la plupart des Pythons:
$ cat my_script.py
#!/usr/bin/env python2.6
import json
print "hello, json"
Si vous avez juste besoin de faire la distinction entre Python 2.x et Python 3.x, les versions récentes de Python 3 fournissent également un python3
nom:
$ cat my_script.py
#!/usr/bin/env python3
import json
print("hello, json")
which python
rendement /usr/bin/python
, un chemin de répertoire local pourrait être codé en dur: #!/usr/bin/python
. Mais c'est moins flexible que celui #!/usr/bin/env python
qui a une application globale.
Afin d'exécuter le script python, nous devons dire au shell trois choses:
Le shebang #!
accomplit (1.). Le shebang commence par un #
car le #
personnage est un marqueur de commentaire dans de nombreux langages de script. Le contenu de la ligne shebang est donc automatiquement ignoré par l'interprète.
La env
commande accomplit (2.) et (3.). Pour citer "grawity"
Une utilisation courante de la
env
commande est de lancer des interprètes, en utilisant le fait que env recherchera $ PATH pour la commande qu'on lui demande de lancer. Étant donné que la ligne shebang nécessite la spécification d'un chemin absolu et que l'emplacement des divers interprètes (perl, bash, python) peut varier considérablement, il est courant d'utiliser:
#!/usr/bin/env perl
au lieu d'essayer de deviner s'il s'agit de / bin / perl, / usr / bin / perl, / usr / local / bin / perl, / usr / local / pkg / perl, / fileserver / usr / bin / perl ou / home / MrDaniel / usr / bin / perl sur le système de l'utilisateur ...D'un autre côté, env est presque toujours dans / usr / bin / env. (Sauf dans les cas où ce n'est pas le cas; certains systèmes peuvent utiliser / bin / env, mais c'est une occasion assez rare et ne se produit que sur des systèmes non Linux.)
Votre question est peut-être en ce sens:
Si vous souhaitez utiliser: $python myscript.py
Vous n'avez pas du tout besoin de cette ligne. Le système appellera python puis l'interpréteur python exécutera votre script.
Mais si vous avez l'intention d'utiliser: $./myscript.py
En l'appelant directement comme un programme normal ou un script bash, vous devez écrire cette ligne pour spécifier au système quel programme utiliser pour l'exécuter, (et aussi le rendre exécutable avec chmod 755
)
L' exec
appel système du noyau Linux comprend #!
nativement shebangs ( )
Quand tu fais bash:
./something
sous Linux, cela appelle l' exec
appel système avec le chemin ./something
.
Cette ligne du noyau est appelée sur le fichier transmis à exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
Il lit les tout premiers octets du fichier et les compare à #!
.
Si la comparaison est vraie, le reste de la ligne est analysé par le noyau Linux, ce qui en fait un autre exec
appel avec chemin /usr/bin/env python
et fichier actuel comme premier argument:
/usr/bin/env python /path/to/script.py
et cela fonctionne pour tout langage de script qui utilise #
comme caractère de commentaire.
Et oui, vous pouvez faire une boucle infinie avec:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
Bash reconnaît l'erreur:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#!
se trouve être lisible par l'homme, mais ce n'est pas obligatoire.
Si le fichier a commencé avec différents octets, l' exec
appel système utiliserait un gestionnaire différent. L'autre gestionnaire intégré le plus important concerne les fichiers exécutables ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 qui vérifie les octets 7f 45 4c 46
(qui se trouvent également être humains) lisible pour .ELF
). Confirmons qu'en lisant les 4 premiers octets de /bin/ls
, qui est un exécutable ELF:
head -c 4 "$(which ls)" | hd
production:
00000000 7f 45 4c 46 |.ELF|
00000004
Ainsi, lorsque le noyau voit ces octets, il prend le fichier ELF, le place correctement en mémoire et démarre un nouveau processus avec lui. Voir aussi: Comment le noyau obtient-il un fichier binaire exécutable sous Linux?
Enfin, vous pouvez ajouter vos propres gestionnaires de shebang avec le binfmt_misc
mécanisme. Par exemple, vous pouvez ajouter un gestionnaire personnalisé pour les .jar
fichiers . Ce mécanisme prend même en charge les gestionnaires par extension de fichier. Une autre application consiste à exécuter de manière transparente des exécutables d'une architecture différente avec QEMU .
Je ne pense pas que POSIX spécifie des shebangs cependant: https://unix.stackexchange.com/a/346214/32558 , bien qu'il mentionne dans les sections sur la justification et sous la forme "si les scripts exécutables sont pris en charge par le système, quelque chose peut se produire". macOS et FreeBSD semblent également l'implémenter.
PATH
motivation de recherche
Probablement, une grande motivation pour l'existence de shebangs est le fait que sous Linux, nous voulons souvent exécuter des commandes à partir PATH
de:
basename-of-command
au lieu de:
/full/path/to/basename-of-command
Mais alors, sans le mécanisme shebang, comment Linux saurait-il lancer chaque type de fichier?
Codage en dur de l'extension dans les commandes:
basename-of-command.py
ou implémentant la recherche PATH sur chaque interprète:
python basename-of-command
serait une possibilité, mais cela a le problème majeur que tout se casse si nous décidons de refactoriser la commande dans une autre langue.
Shebangs résout magnifiquement ce problème.
Techniquement, en Python, ce n'est qu'une ligne de commentaire.
Cette ligne n'est utilisée que si vous exécutez le script py à partir du shell (à partir de la ligne de commande). Ceci est connu comme le " Shebang !" , et il est utilisé dans diverses situations, pas seulement avec des scripts Python.
Ici, il demande au shell de démarrer une version spécifique de Python (pour prendre soin du reste du fichier.
py.exe
. Cela fait partie d'une installation Python standard.
La principale raison pour cela est de rendre le script portable dans les environnements de système d'exploitation.
Par exemple sous mingw, les scripts python utilisent:
#!/c/python3k/python
et sous distribution GNU / Linux c'est soit:
#!/usr/local/bin/python
ou
#!/usr/bin/python
et sous le meilleur système commercial Unix sw / hw de tous (OS / X), c'est:
#!/Applications/MacPython 2.5/python
ou sur FreeBSD:
#!/usr/local/bin/python
Cependant, toutes ces différences peuvent rendre le script portable à tous en utilisant:
#!/usr/bin/env python
/usr/bin/python
. Sous Linux, le Python installé par le système l'est aussi presque certainement /usr/bin/python
(je n'ai jamais rien vu d'autre et cela n'aurait aucun sens). Notez qu'il peut y avoir des systèmes qui n'en ont pas /usr/bin/env
.
python
n'est pas si portable, c'est l'interpréteur Python par défaut de la distribution. Arch Linux utilise par défaut Python 3 depuis longtemps et les distributions peuvent y penser aussi parce que Python 2 n'est pris en charge que jusqu'en 2020.
Il est probablement logique de souligner une chose que la plupart ont manqué, ce qui peut empêcher une compréhension immédiate. Lorsque vous tapez python
terminal, vous ne fournissez normalement pas de chemin complet. Au lieu de cela, l'exécutable est recherché dans PATH
la variable d'environnement. À son tour, lorsque vous souhaitez exécuter un programme Python directement /path/to/app.py
, vous devez indiquer au shell quel interpréteur utiliser (via le hashbang , ce que les autres contributeurs expliquent ci-dessus).
Hashbang attend le chemin complet vers un interprète. Ainsi, pour exécuter votre programme Python directement, vous devez fournir un chemin complet vers le binaire Python qui varie considérablement, en particulier compte tenu de l'utilisation de virtualenv . Pour aborder la portabilité, l'astuce avec /usr/bin/env
est utilisée. Ce dernier est à l'origine destiné à modifier l'environnement en place et à exécuter une commande dans celui-ci. Lorsqu'aucune modification n'est fournie, il exécute la commande dans l'environnement actuel, ce qui entraîne effectivement la mêmePATH
recherche qui fait l'affaire.
Il s'agit d'une convention shell qui indique au shell quel programme peut exécuter le script.
#! / usr / bin / env python
résout un chemin vers le binaire Python.
Il est recommandé, proposé dans la documentation:
2.2.2. Scripts Python exécutables
Sur les systèmes BSD'ish Unix, les scripts Python peuvent être rendus directement exécutables, comme les scripts shell, en mettant la ligne
#! /usr/bin/env python3.2
depuis http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
Vous pouvez essayer ce problème en utilisant virtualenv
Voici test.py
#! /usr/bin/env python
import sys
print(sys.version)
Créer des environnements virtuels
virtualenv test2.6 -p /usr/bin/python2.6
virtualenv test2.7 -p /usr/bin/python2.7
activer chaque environnement puis vérifier les différences
echo $PATH
./test.py
Il spécifie simplement quel interprète vous souhaitez utiliser. Pour comprendre cela, créez un fichier via le terminal en faisant touch test.py
, puis tapez dans ce fichier ce qui suit:
#!/usr/bin/env python3
print "test"
et faites chmod +x test.py
pour rendre votre script exécutable. Après cela, ./test.py
vous devriez obtenir une erreur indiquant:
File "./test.py", line 2
print "test"
^
SyntaxError: Missing parentheses in call to 'print'
car python3 ne prend pas en charge l'opérateur d'impression.
Maintenant, allez-y et changez la première ligne de votre code en:
#!/usr/bin/env python2
et cela fonctionnera, en imprimant test
sur stdout, car python2 prend en charge l'opérateur d'impression. Ainsi, vous avez maintenant appris à basculer entre les interpréteurs de script.
Il me semble que les fichiers fonctionnent de la même manière sans cette ligne.
Si oui, alors vous exécutez peut-être le programme Python sous Windows? Windows n'utilise pas cette ligne - à la place, il utilise l'extension de nom de fichier pour exécuter le programme associé à l'extension de fichier.
Cependant en 2011, un "lanceur Python" a été développé qui imite (dans une certaine mesure) ce comportement Linux pour Windows. Ceci se limite uniquement au choix de l'interpréteur Python à exécuter - par exemple pour sélectionner entre Python 2 et Python 3 sur un système où les deux sont installés. Le lanceur est éventuellement installé comme py.exe
par l'installation Python et peut être associé à des .py
fichiers afin que le lanceur vérifie cette ligne et lance à son tour la version d'interpréteur Python spécifiée.
$ python myscript.py
.
Cela signifie plus d'informations historiques qu'une réponse «réelle».
Rappelez - vous que dans la journée vous eu beaucoup de unix comme les systèmes d' exploitation dont les concepteurs avaient tous leur propre idée de l' endroit où mettre des choses, et parfois ne comprennent pas Python, Perl, Bash, ou beaucoup d'autres GNU / Open Source substance du tout .
Cela était même vrai pour différentes distributions Linux. Sous Linux - pré-FHS [1] - vous pourriez avoir python dans / usr / bin / ou / usr / local / bin /. Ou il n'a peut-être pas été installé, alors vous avez construit le vôtre et le mettez dans ~ / bin
Solaris a été le pire sur lequel j'ai jamais travaillé, en partie lors de la transition de Berkeley Unix au système V. Vous pouvez vous retrouver avec des choses dans / usr /, / usr / local /, / usr / ucb, / opt / etc. pour certains très longs chemins. J'ai des souvenirs de ce que Sunfreeware.com a installé chaque paquet dans son propre répertoire, mais je ne me souviens pas s'il a lié les binaires dans / usr / bin ou non.
Oh, et parfois / usr / bin était sur un serveur NFS [2].
L' env
utilitaire a donc été développé pour contourner ce problème.
Ensuite, vous pouviez écrire #!/bin/env interpreter
et tant que le chemin était correct, les choses avaient une chance raisonnable de courir. Bien sûr, raisonnable signifiait (pour Python et Perl) que vous aviez également défini les variables d'environnement appropriées. Pour bash / ksh / zsh, cela a juste fonctionné.
C'était important parce que les gens passaient autour des scripts shell (comme perl et python) et si vous aviez codé en dur / usr / bin / python sur votre poste de travail Red Hat Linux, ça allait mal se passer sur un SGI ... enfin, non , Je pense que IRIX a mis le python au bon endroit. Mais sur une station Sparc, il pourrait ne pas fonctionner du tout.
Ma station Sparc me manque. Mais pas beaucoup. Ok, maintenant tu me fais traîner sur E-Bay. Bastages.
[1] Norme de hiérarchie du système de fichiers. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] Oui, et parfois les gens font encore des trucs comme ça. Et non, je ne portais ni navet NI oignon à la ceinture.
Si vous exécutez votre script dans un environnement virtuel, par exemple venv
, l'exécution which python
en travaillant sur venv
affichera le chemin vers l'interpréteur Python:
~/Envs/venv/bin/python
Notez que le nom de l'environnement virtuel est incorporé dans le chemin d'accès à l'interpréteur Python. Par conséquent, le codage en dur de ce chemin dans votre script entraînera deux problèmes:
Par conséquent, pour ajouter à la réponse de Jonathan , le shebang idéal est #!/usr/bin/env python
, non seulement pour la portabilité entre les systèmes d'exploitation, mais aussi pour la portabilité entre les environnements virtuels!
Compte tenu des problèmes de portabilité entre python2
et python3
, vous devez toujours spécifier l'une ou l'autre version, sauf si votre programme est compatible avec les deux.
Certaines distributions expédiez un python
lien symbolique à python3
un certain temps maintenant - ne comptez pas sur l' python
êtrepython2
.
C'est ce que souligne le PEP 394 :
Afin de tolérer les différences entre plates-formes, tout nouveau code qui doit appeler l'interpréteur Python ne doit pas spécifier python, mais doit plutôt spécifier python2 ou python3 (ou les versions plus spécifiques python2.x et python3.x; voir les notes de migration ) . Cette distinction doit être faite dans les shebangs, lors de l'appel à partir d'un script shell, lors de l'appel via l'appel system (), ou lors de l'appel dans tout autre contexte.
Il vous permet de sélectionner l'exécutable que vous souhaitez utiliser; ce qui est très pratique si vous avez peut-être plusieurs installations python et différents modules dans chacun et que vous souhaitez choisir. par exemple
#!/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 $ALTERNATIVE_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())
cela indique au script où se trouve le répertoire python!
#! /usr/bin/env python
#!/usr/bin/env python
haut.