Pourquoi Python sous Linux requiert-il la ligne #! / Usr / bin / python?


50

Question assez simple: Sous Linux, pourquoi Python a-t-il besoin de la ligne?

#!/usr/bin/python

au début d'un fichier python, puisque Windows ne le fait pas?

Qu'est ce que ça fait? Parce que la description "Links to Python" est un peu vague ...


29
Les réponses ci-dessous sont toutes correctes. Aucune d’entre elles ne explique pourquoi Windows n’a pas besoin de cette ligne. Windows dépend de l’extension du fichier (la partie après le .) pour déterminer le type de fichier. Même Windows s'éloigne de cela: examinez les premières lignes du fichier Microsoft Word, qui indiqueront qu'il s'agit en fait d'un fichier Microsoft Word.
Charles Green

10
Selon l’éléphant dans la pièce, vous ne devez JAMAIS utiliser / usr / bin / python si vous n’êtes pas compatible avec python 2 et 3. Reason: arch la lie à python3, un geste reconnu par le PSF, qui le déconseille lui-même.
Pourtant, un autre utilisateur

7
C'est implicite, mais pas explicitement indiqué dans les réponses ci-dessous, que ce n'est pas obligatoire . Cela est nécessaire si vous voulez exécuter le script uniquement à partir de son propre nom. Vous pouvez toujours courir à la python myscript.pyplace.
Chris H

3
@ Charles Green, nous ne sommes pas censés savoir pourquoi Windows ne le sait pas ;-) Cela dépend de SO.
Rinzwind

2
@YetAnotherUser Cela fait six ans et onze mois depuis la sortie de Python 3, à ce stade, je pense qu'il serait préférable que les utilisateurs passent à 3 et spécifient explicitement l'utilisation de 2 lorsque cela est nécessaire.
JAB

Réponses:


59

Python n’a aucune exigence particulière sur Linux. C'est le chargeur de programme sous Unix / Linux qui utilise la ligne "shebang", comme on l'appelle. Il s’agit en réalité d’une fonctionnalité plutôt que d’une limitation, mais nous y reviendrons dans un instant. La page Wiki sur "shebang" contient plus de détails, mais je vais essayer de vous donner un aperçu ainsi qu'une comparaison avec Windows ici.

Tout d’abord, regardons la situation sous Windows:

  • Lorsque vous essayez d'ouvrir ou d'exécuter un fichier, Windows examine d'abord l' extension de ce fichier. Ceci est la dernière partie du nom de fichier commençant par. .Dans le cas de fichiers Python, il s'agit généralement .py.
  • Windows recherche l'action à entreprendre en fonction de l'extension de fichier.
    • Ces informations sont enregistrées dans le registre Windows. Lorsque Python est installé, il indique généralement à Windows que les .pyfichiers doivent être ouverts à l'aide de l' application Python nouvellement installée (c'est-à-dire l'interpréteur Python).
    • Plusieurs types de fichiers ont des comportements intégrés; Par exemple, les fichiers exécutables (tels que l'interpréteur Python lui-même) doivent se terminer .exeet les .batfichiers sont exécutés sous forme de scripts batch Windows.
    • L'action entreprise pour un type de fichier particulier est personnalisable . Vous pouvez, par exemple, dire à Windows qu’au lieu d’exécuter des .pyfichiers python.exe, vous devez les ouvrir avec un autre programme, tel que l’éditeur de texte notepad.exe.
      • Dans ce cas, pour exécuter un script Python, vous devez appeler manuellementpython <scriptname>.py (ou écrire un .batfichier pour le faire à votre place).

Maintenant, que se passe-t-il s'il y a une ligne shebang ( #!/usr/bin/pythonou #!/usr/bin/env python) en haut du script Python? Eh bien, puisqu'il #s'agit d'une ligne de commentaire en Python, l'interpréteur Python l'ignore. C'est l'une des raisons pour lesquelles la plupart des langages de script utilisés dans le monde Unix / Linux utilisent #le début des lignes de commentaire.

C'est donc un peu trompeur de dire que Windows "n'a pas besoin" de la #!ligne; Windows ne voit pas la #!ligne et s'appuie en fait sur l'extension de fichier pour lui indiquer quoi faire. Cela a quelques inconvénients:

  • Vous devez nommer les scripts Python avec .pyà la fin pour qu'ils soient automatiquement reconnus comme tels.
  • Il n'y a pas de moyen facile de distinguer les scripts Python2 des scripts Python3.
  • Comme indiqué précédemment, si vous modifiez le comportement de lancement par défaut pour le .pytype de fichier, Windows n'exécutera plus automatiquement ces scripts avec Python. Notez que cela pourrait être fait involontairement.

Voyons maintenant comment Unix / Linux lance les scripts:

La première chose à noter est que, contrairement à Windows, Unix / Linux n'essaye pas d '"ouvrir" les scripts Python en utilisant un programme particulier, du moins conceptuellement. le système d'exploitation sait que le script est quelque chose qui peut être exécuté à cause de quelque chose appelé le "bit d'exécution" (qui est en dehors du champ de cette réponse). Donc, si vous tapez accidentellement #!/usr/bin/pthonau lieu de #!/usr/bin/python, vous obtiendrez un message d'erreur incluant ce texte:

/usr/bin/pthon: bad interpreter: No such file or directory.

Le mot "interprète" nous donne un indice sur le rôle de la ligne shebang (bien que techniquement, le programme spécifié puisse être autre chose qu'un interpréteur, tel qu'un catéditeur de texte). Lorsque vous essayez d'exécuter un fichier, voici ce qui se passe:

  • Le chargeur de programme Unix / Linux examine les deux premiers octets de ce fichier; si ces deux octets sont #!, le chargeur interprète le reste de la ligne shebang (à l'exclusion du shebang lui-même) en tant que commande permettant de lancer un interpréteur avec lequel exécuter le contenu du fichier sous forme de script.
  • Le chargeur de programme lance l'interpréteur spécifié, lui fournissant le chemin du fichier d'origine en tant qu'argument.

Cela présente quelques avantages:

  • Le scénariste a plus de contrôle sur l'interpréteur utilisé (ce qui résout le problème Python2 / Python3) et peut parfois lui transmettre un argument supplémentaire (voir la page Wiki pour plus de détails).
  • Le nom de fichier du script est ignoré , vous pouvez donc nommer les scripts Python comme vous le souhaitez.

Notez enfin que Unix / Linux n’a pas besoin de la ligne shebang pour exécuter un script Python. Rappelez-vous que la ligne shebang ne permet en réalité au chargeur de programme de sélectionner un interprète. Mais comme dans Windows, cela peut être fait manuellement:

python <myscript>

1
Sous Windows , vous pouvez facilement avoir .py2et .py3extensions pour Python 2 / Python 3 scripts. Ainsi, Linux (+ x bit) et Windows (extension de fichier) ont tous deux besoin de métadonnées dans le système de fichiers. La principale différence est que le bit + x est plus facilement perdu en transit. Ce n'est pas nécessairement un inconvénient.
MSalters

1
@MSalters Le bit d'exécution contient également beaucoup moins d'informations codées. Et notez que vous pouvez avoir plusieurs interprètes Python2 sur un système donné (il existait une situation similaire avec Ruby et d’autres langues dans un de mes emplois précédents); Traiter cela via la ligne shebang est presque trivial, alors que la situation sur Windows devient beaucoup moins facile à gérer, plus vous essayez de gérer plusieurs types de fichiers similaires.
Kyle Strand

En outre, l'extension compte-t-elle vraiment comme "métadonnées"? C'est juste une partie du nom de fichier.
Kyle Strand

2
Les métadonnées d'un fichier incluent l'intégralité du nom de fichier, l'heure de création, les bits d'accès, etc. Seul le contenu lui-même est constitué de données et non de métadonnées. En ce qui concerne les "interprètes multiples", c’est vraiment un problème et c'est pourquoi il ne devrait pas être dans la ligne de base. Et si vous avez /usr/bin/i686/pythonet /usr/bin/amd64/python? Parfaitement raisonnable, mais cela rompt les scripts python sur lesquels repose une hypothèse codée en dur /usr/bin/python. Le choix de l'interprète n'est pas un choix du scénariste, mais de l'utilisateur du script, le scénariste n'a à choisir que la langue (dialecte).
MSalters

1
@MSalters Eh bien, c'est pour ça que /usr/bin/envc'est, avec les scripts env-setup. Quelle est la version Windows de cela? Vous exécutez un regeditscript juste avant de lancer un .pyfichier pour vous assurer d’obtenir l’interprète souhaité?
Kyle Strand

41

La ligne que vous avez indiquée est utilisée pour indiquer à l'ordinateur le programme / interpréteur à utiliser lors de l'exécution directe du fichier / script, ainsi que tous les arguments devant être transmis à ce programme lors de l'exécution du script. Ceci n’est cependant pas une exigence de Python , mais bien du noyau / système Linux si vous souhaitez exécuter le script directement (et ne pas le transmettre à Python à l’aide de la syntaxe ci-dessous).

Ce n'est pas nécessaire si vous allez exécuter python script.pyou similaire. Cela n'est nécessaire que si vous avez l'intention d'exécuter le script / fichier directement, sans fournir également l'interpréteur à utiliser (tel que python).


Pour un script Bash, cela ressemblerait à ceci:

#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;

Cela indiquerait au système que, lorsqu’il est exécuté, il doit être exécuté via l’ /bin/bashun des langages shell / script sur le système.


Pour le code Python, cependant, ici, vous souhaiterez que le fichier exécutable s’exécute via Python, de sorte que vous lui indiquiez l’interpréteur que vous souhaitez y exécuter.

#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()

Ceci, comme pour Bash, indique qu'il /usr/bin/pythonconvient de l'utiliser (il s'agit probablement de Python 2 ou de Python 3, en fonction de la configuration de votre système).


De cette façon, vous pouvez courir ./filename.pyou ./executableou ./scripttorundirectement.

Sans cette ligne au début, et en supposant que vous ayez défini le fichier / script pour qu'il soit exécutable, et en supposant que vous travaillez avec un script Python, vous devrez exécuter python filename.pyou similaire si vous n'aviez pas la #!/usr/bin/pythonligne. (Pour un script Bash, vous devrez le faire bash script.sh, ou similaire pour d'autres scripts / langages, tels que Perl, Ruby, etc.)

La mise en évidence de la syntaxe ci-dessus est spécifique à la langue dans chaque section, même si cela n’a pas vraiment d’importance.


1
Une chose intéressante à ajouter serait qu'il est possible de spécifier des paramètres supplémentaires après le tralala lui - même, dans la plupart des cas , de la même manière que si l'interprète a été appelé directement ( #!/bin/bash -x, #!/usr/bin/perl -lan, etc.).
Kos

7
@ Kos: Je pense que vous pouvez spécifier exactement un argument supplémentaire, qui a été un PITA, alors que l'on devrait (devrait) l'utiliser /usr/bin/env pythonpour obtenir le python correct.
unperson325680

@progo Vous ne savez pas quel est le problème env, mais le problème ne semble pas être le nombre d'arguments: #!/usr/bin/perl -l -a -na trois arguments mais cela fonctionne. Encore une fois, je ne suis pas capable de poser le problème exact.
kos

Lorsque vous appelez explicitement un interpréteur avec le script en argument, il n’ya aucune raison de commencer par ce dernier ./. En d'autres termes, juste python filename.pyou bash script.shfonctionnera bien. La seule raison d'inclure ./est dans un nom de commande, lorsque vous souhaitez indiquer au shell de ne pas effectuer de recherche $PATH(qui ne trouvera probablement pas de fichiers dans le répertoire en cours), mais de prendre le chemin que vous avez spécifié. Mais cela ne s'applique pas aux arguments de commande.
Marc van Leeuwen

@ Kos: Le problème pourrait être lié à la manière dont envle noyau reçoit le reste des arguments. Ils pourraient tous être considérés comme un argument de grande taille sans scission par espace. Désolé pour l'articulation, je ne me souviens plus très bien des détails
unperson325680

16

La ligne:

#!/usr/bin/python

s'appelle le 'shebang' et indique le chemin d'accès au binaire de l'interpréteur qui sera utilisé pour interpréter le reste des commandes du fichier. C'est généralement la première ligne d'un script.

La ligne #!/usr/bin/pythonindique donc que le contenu du fichier sera interprété par le pythonbinaire situé à /usr/bin/python.

Notez que la ligne shebang est analysée par le noyau, puis le script sera appelé comme argument:

python script_name

De même en cas de #!/bin/bash:

bash script_name

2
Je ne pense pas avoir jamais vu un trait d'union dans shebang. Puisque le mot est formé de "hash" et de "bang", votre orthographe n’est pas très claire, car on dirait qu’elle est une combinaison de "elle" et de "bang".
Kyle Strand

Vous pouvez l'appeler hashbang( #= "hash") ou shebang( #= "sharp"), selon le nom que vous donnez au #personnage. Cependant, shebangest en effet plus commun. @KyleStrand
Byte Commander

7

Techniquement, cela ne l'exige pas. Cela nécessite un chemin d'accès à l'environnement où votre script s'exécute. Il serait préférable que vos futurs scripts incluent / usr / bin / env, spécifiez python. Cela garantit que votre script s'exécute dans l'environnement Python, peu importe où Python est installé. Vous voulez faire cela pour des raisons de compatibilité, vous ne pouvez pas être sûr que la prochaine personne avec laquelle vous partagez votre code aura installé python dans usr / bin / python, ou qu'elle aura les autorisations nécessaires sur ces fichiers système.

Voici un Q & A similaire à partir du débordement de pile .

Voici à quoi cela ressemble dans votre script:

#!/usr/bin/env python

Je vois aussi un problème concernant la spécification de python3. Voici comment faire:

#!/usr/bin/env python3

5

Sous Linux, Python peut nécessiter ou non la ligne #!(shebang). Cela dépend de la manière dont les codes Python sont gérés, qu'ils soient exécutés en mode interactif Python ou dans un script Python.

Le mode interactif Python permet à l’utilisateur de taper et d’exécuter des codes Python directement, ce qui ne nécessite pas la ligne shebang. Pour exécuter le mode interactif, ouvrez un terminal et tapez pythonpour Python 2.X ou python3pour Python 3.X.

$  python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

$  python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Le script Python permet à l'utilisateur d'écrire et de sauvegarder les codes Python dans un fichier en texte brut, puis de les exécuter ultérieurement. Cela peut ou peut ne pas nécessiter la ligne shebang. Cependant, il existe deux raisons connues pour lesquelles la ligne shebang est requise pour utiliser un script Python sous Linux.

  1. exécuter des codes Python dans un script exécutable, c'est-à-dire définir comment les codes doivent être exécutés et en utilisant quel interpréteur;

  2. pour exécuter les codes Python en fonction d'une version spécifique de Python, c.-à-d. des codes compatibles avec Python 2.X ou Python 3.X uniquement

Pratique avec les scripts Python

Vous trouverez ci-dessous la liste et le contenu des fichiers, que j’ai utilisés pour montrer aux cas où la ligne #!(shebang) est requise ou non.

$  ls -ln *.py
-rw-rw-r-- 1 1000 1000  94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py

$  file *.py
hello1.py:  ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py:  Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py:  Python script, ASCII text executable
  • hello1.py contient uniquement du code source.

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2.py contient le code source et la ligne shebang.

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2e.pycontient même que hello2.pyet rendu exécutable.

  • hello3.pycontient same as hello2.py, sauf qu'il est adapté pour fonctionner avec Python 3 en renommant la première ligne #!/usr/bin/env python3.

  • hello3e.pycontient même que hello3.pyet rendu exécutable.

  • hello3m.pycontient la même chose que hello3.pyet est exécutable, sauf l' Write Unicode BOMoption enregistrée dans l'éditeur de texte, à savoir Mousepad.

Au-delà de ce point, deux méthodes d’exécution des scripts Python seront présentées à l’utilisateur. Les deux méthodes ont été démontrées ci-dessous.

Méthode 1: Exécuter avec le programme Python

Vous trouverez ci-dessous les commandes et les résultats lors de l’exécution du code source avec Python 2 et Python 3.

$  python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Les deux versions de Python ont pu exécuter le script avec succès. Par conséquent, la ligne shebang n'est pas requise lors de l'exécution du script Python via pythonou python3commande.

Méthode 2: Exécuter en tant que script Python

Vous trouverez ci-dessous les commandes et les résultats lors de l'exécution du code source avec la ligne shebang, qui ne sont adaptés à aucun des deux, Python 2 et Python 3, y compris les cas non exécutables et exécutables.

$  ./hello1.py
bash: ./hello1.py: Permission denied

$  ./hello2.py
bash: ./hello2.py: Permission denied

$  ./hello3.py
bash: ./hello3.py: Permission denied

$  ./hello2e.py 
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  ./hello3e.py 
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Les trois premiers scripts ont échoué car ils ne sont pas exécutables, qu'ils aient ou non la ligne shebang (pour la preuve, voir l' exemple supplémentaire ci-dessous). Les deux derniers scripts ont une ligne shebang et sont exécutables.

Apparemment, un script qui a été rendu exécutable est essentiellement inutile sans la ligne shebang. Par conséquent, la ligne shebang est requise et le script doit être exécutable lors de l'exécution des codes Python dans un script exécutable.

Quand shebang ne fonctionne pas

Dans mon exemple préparé et testé, l'exécution en hello3m.pytant que script exécutable a échoué et a renvoyé une erreur.

$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory

C'est une limitation connue que shebang ne fonctionne pas ou devient invalide. Lorsqu'un fichier est enregistré en tant que BOM Unicode (Byte Order Mark), son exécution normale en tant que script Python est impossible.

Exemple supplémentaire

Cet exemple supplémentaire ne doit être considéré que comme une preuve à l'appui. L'utilisateur doit éviter d'exécuter cet exemple, même si le résultat est inoffensif.

J'ai créé un autre fichier appelé hello1e.py, qui contient le même hello1.pyet qui est rendu exécutable. L'exécution de ce script a renvoyé une erreur de syntaxe.

$  ./hello1e.py 
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'

Lors de l'exécution de ce script, le curseur de la souris devient d'abord un signe plus et ne fait rien en apparence. L'erreur de syntaxe ne sera pas affichée jusqu'à ce que je clique sur la fenêtre du bureau ou du terminal. Ensuite, ce script créera un sysfichier dans le même répertoire que le script.

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

Le sysfichier a été identifié en tant que fichier PostScript, sans extension de fichier. Ce fichier peut être ouvert dans la visionneuse de documents, par exemple Evince, et le fichier contenait en fait une capture d'écran de la fenêtre sur laquelle j'avais cliqué précédemment. D'après mon expérience, le fichier peut atteindre quelques mégaoctets.

Une fois encore, la ligne shebang est requise et le script doit être exécutable lors de l'exécution du script Python en tant que script exécutable. Sinon, le script se comportera de la manière décrite ci-dessus.

Notes complémentaires

Le terme "rendu exécutable" ou "doit être exécutable" fait référence à la permission d'exécuter le script. Ceci est effectué en exécutant la chmod +x FILENAMEcommande dans Terminal ou en cochant l’option "Autoriser l’exécution de ce fichier en tant que programme" ou quelque chose de similaire dans la fenêtre Propriétés , dans un gestionnaire de fichiers.

Alors que d'autres réponses existantes couvraient presque tout, cette réponse a adopté une approche différente en utilisant des exemples pratiques pour expliquer le problème. La syntaxe du code a été écrite avec soin, de telle sorte que les exemples puissent être exécutés avec Python 2 ou Python 3, en l’état.

Les codes Python ont été adaptés de Utilisation de Python sous Windows et Utilisation de Python sous Unix , avec un code supplémentaire à une ligne de l'omniprésent "Hello, World!" programme.

Tous les codes et toutes les commandes ont été entièrement testés et fonctionnent dans le système Xubuntu 14.04, sur lequel Python 2.7 et Python 3.4 étaient installés par défaut.


4

Cela signifie que lorsque ce fichier est exécuté, votre ordinateur sait qu'il peut être exécuté avec le programme /usr/bin/python. C'est ainsi que vous le différencierez d'une autre langue, telle que bash où vous le feriez #!/bin/bash. C'est pour que vous puissiez simplement lancer:

./[file-to-execute]

Et il saura avec quel fichier l'exécuter, plutôt que de devoir spécifier vous-même quelque chose comme:

python ./[file-to-execute].py

La #!partie est généralement arbitrée comme un shebang ou un crunch bang .


2
Aussi un hashbang.
Naftuli Kay

1

Si vous avez plusieurs versions de Python installées, /usr/bin/envassurez-vous que l'interpréteur utilisé est la première de votre environnement $PATH. L'alternative serait de coder en dur quelque chose comme #!/usr/bin/python;

Sous Unix, un fichier exécutable censé être interprété peut indiquer quel interpréteur utiliser en #!commençant par le début de la première ligne, suivi de l'interpréteur (et de tous les indicateurs dont il pourrait avoir besoin).

Cette règle ne s'applique qu'aux systèmes UNIX.


0

utile pour les systèmes d'exploitation comme Linux où Python 2.x est toujours la norme, mais la plupart des gens téléchargent également la version 3.x.

2.x serait exécuté par défaut. Donc, mon code 3.x, je préfixe avec #! / Usr / bin / env python3 afin que 3.x exécute le code. Je peux même spécifier jusqu'à la révision mineure (python 3.xyz) si j'ai choisi les versions bêta ou juste des versions légèrement plus anciennes.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.