Question Pourquoi les gens écrivent le #! / Usr / bin / env python shebang sur la première ligne d'un script Python?


Il me semble que les fichiers fonctionnent de la même façon sans cette ligne.


820
2018-03-11 23:50


origine


Réponses:


Si vous avez plusieurs versions de Python installées, /usr/bin/env veillera à ce que l'interprète utilisé est le premier sur votre environnement $PATH. L'alternative serait de coder en dur quelque chose comme #!/usr/bin/python; c'est bon, mais moins flexible.

Dans Unix, un exécutable fichier qui est destiné à être interprété peut indiquer quel interprète utiliser en ayant un #! au début de la première ligne, suivi par l'interprète (et tous les drapeaux 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 pas de mal, et vous aidera si vous copiez ce script sur une plate-forme avec une base Unix, telle que Linux, Mac, etc).


902
2018-03-11 23:52



C'est ce qu'on appelle le ligne de shebang. Comme le L'entrée Wikipédia explique:

En informatique, un shebang (aussi appelé hashbang, hashpling, pound bang, ou crunchbang) fait référence aux caractères "#!" lorsqu'il s'agit des deux premiers caractères d'une directive d'interpréteur en tant que première ligne d'un fichier texte. Dans un système d'exploitation de type Unix, le chargeur de programme 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 en utilisant l'interpréteur spécifié par le reste de la première ligne du fichier.

Voir aussi Entrée FAQ Unix.

Même sur Windows, où la ligne shebang ne détermine pas l'interpréteur à exécuter, vous pouvez passer des options à l'interpréteur en les spécifiant sur la ligne shebang. Je trouve utile de garder une ligne générique shebang dans des scripts uniques (comme ceux que j'écris en répondant à des questions sur SO), donc je peux les tester rapidement sur Windows et ArchLinux.

le utilitaire env vous permet d'invoquer une commande sur le chemin:

Le premier argument restant spécifie le nom du programme à appeler; il est recherché en fonction de la PATH variable d'environnement. Tous les arguments restants sont passés en arguments de ce programme.


222
2018-03-11 23:52



En 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 par l'utilisation imprudente de /usr/bin/env 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 genre 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 python3 prénom:

$ cat my_script.py 
#!/usr/bin/env python3
import json
print("hello, json")

135
2018-03-12 00:35



Pour exécuter le script python, nous devons dire au shell trois choses:

  1. Que le fichier est un script
  2. Quel interprète voulons-nous exécuter le script?
  3. Le chemin de cet interprète

Le shebang #! accomplit (1.). Le shebang commence par un # parce que le #character 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.

le env commande accomplit (2.) et (3.). Pour citer "grawity"

Une utilisation commune du env commande est de lancer des interprètes, en faisant   utilisation du fait que env cherchera $ PATH pour la commande qu'on lui dit   lancer. Depuis la ligne shebang nécessite un chemin absolu pour être   spécifié, et depuis l'emplacement de divers interprètes (perl, bash,   python) peut varier beaucoup, il est courant d'utiliser:

#!/usr/bin/env perlau lieu d'essayer de deviner si c'est   / 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 compte de l'utilisateur   système...

D'un autre côté, env est presque toujours dans / usr / bin / env. (Sauf dans   cas où ce n'est pas le cas; certains systèmes peuvent utiliser / bin / env, mais c'est un   occassion assez rare et ne se produit que sur des systèmes non-Linux.)


78
2018-03-26 00:07



Techniquement, en Python, c'est juste une ligne de commentaire.

Cette ligne n'est utilisée que si vous exécutez le script py de la coquille (à partir de la ligne de commande). C'est connu comme le "Case! ", et il est utilisé dans diverses situations, pas seulement avec des scripts Python.

Ici, il ordonne au shell de démarrer un version spécifique de Python (pour prendre soin du reste du fichier.


38
2018-03-11 23:58



Peut-être que votre question est dans ce sens:

Si vous voulez utiliser: $python myscript.py

Vous n'avez pas besoin de cette ligne du tout. Le système appellera python, puis l'interpréteur python lancera votre script.

Mais si vous avez l'intention d'utiliser: $./myscript.py

Appelez-le 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)


37
2018-01-17 11:13



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 la distribution GNU / Linux c'est soit:

#!/usr/local/bin/python 

ou

#!/usr/bin/python

et sous le meilleur système commercial sw / hw Unix 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 en utilisant:

#!/usr/bin/env python

34
2017-07-20 22:34



le exec appel système du noyau Linux comprend shebangs (#!) nativement

Quand vous faites sur bash:

./something

sous Linux, cela appelle le 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]! = '!'))

Cela lit les tout premiers octets du fichier et les compare à #!.

Si c'est vrai, alors le reste de la ligne est analysé par le noyau Linux, ce qui fait un autre appel exec avec le chemin /usr/bin/env python et le fichier actuel comme premier argument:

/usr/bin/env python /path/to/script.py

et cela fonctionne pour tout langage de script qui utilise # comme un caractère de commentaire.

Et oui, vous pouvez faire une boucle infinie avec:

#!/a

et un fichier exécutable à /a

#! Il arrive juste d'être lisible par l'homme, mais ce n'est pas nécessaire.

Si le fichier a démarré avec des octets différents, le exec l'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 trouve aussi être lisible par l'homme pour .ELF). Cela lit le fichier ELF, le met dans la mémoire correctement, et commence un nouveau processus avec lui. Voir également: 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 .jar des dossiers. Ce mécanisme prend même en charge les gestionnaires par extension de fichier. Une autre application est de exécuter de manière transparente des exécutables d'une architecture différente avec QEMU.

Je ne pense pas que POSIX spécifie les shebangs: https://unix.stackexchange.com/a/346214/32558 , bien qu'il mentionne dans les sections sur la justification, et dans la forme "si des scripts exécutables sont supportés par le système, quelque chose peut arriver".


23
2017-12-02 18:29



Il est probablement logique de souligner une chose qui a manqué le plus, ce qui peut empêcher une compréhension immédiate. Lorsque vous tapez python dans le terminal, vous ne fournissez pas normalement un chemin complet. Au lieu de cela, l'exécutable est regardé dans PATH variable d'environnement. À son tour, lorsque vous voulez exécuter un programme Python directement, /path/to/app.py, il faut dire à l'interpréteur quel interprète utiliser (via le hashbang, ce que les autres contributeurs expliquent ci-dessus).

Hashbang attend le chemin complet à un interprète. Ainsi, pour exécuter votre programme Python directement, vous devez fournir le chemin complet vers le binaire Python qui varie de manière significative, en particulier compte tenu d'une utilisation de virtualenv. Pour résoudre la portabilité, l'astuce /usr/bin/env est utilisé. Ce dernier est à l'origine destiné à modifier l'environnement sur place et à y exécuter une commande. Lorsqu'aucune modification n'est fournie, elle exécute la commande dans l'environnement actuel, ce qui aboutit à la même chose PATH recherche qui fait l'affaire.

Source d'unix stackexchange


19
2018-03-18 09:31



C'est la manière recommandée, proposée dans la documentation:

2.2.2. Scripts Python exécutables

Sur les systèmes BSD'ish Unix, les scripts Python peuvent être directement créés   exécutable, comme les scripts shell, en mettant la ligne

#! /usr/bin/env python3.2

de http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts


12
2017-12-11 09:34