Comment puis-je utiliser des variables d'environnement dans mon shebang?

J'ai un script Python qui doit être exécuté avec une installation particulière de python. Y at-il un moyen de créer un shebang pour qu'il s'exécute avec $FOO/bar/MyCustomPython ?

La ligne de shebang est très limitée. Sous de nombreuses variantes unix (y compris Linux), vous ne pouvez avoir que deux mots: une command et un seul argument. Il y a aussi souvent une limitation de longueur.

La solution générale consiste à écrire une petite enveloppe. Nommez le script Python foo.py et placez le script shell à côté de foo.py et appelez-le foo . Cette approche ne nécessite aucun en-tête particulier sur le script Python.

 #!/bin/sh exec "$FOO/bar/MyCustomPython" "$0.py" "$@" 

Une autre approche tentante est d'écrire un script wrapper comme celui ci-dessus, et de mettre #!/path/to/wrapper/script comme ligne shebang sur le script Python. Cependant, la plupart des univers ne prennent pas en charge le chaînage des scripts shebang, donc cela ne fonctionnera pas.

Si MyCustomPython était dans le $PATH , vous pourriez utiliser env pour le searchr:

 #!/usr/bin/env MyCustomPython import … 

Une autre approche consiste à faire en sorte que le script soit à la fois un script shell valide (qui charge le bon interpréteur Python sur lui-même) et un script valide dans la langue cible (ici Python). Cela nécessite que vous trouviez un moyen d'écrire un tel script en double langage pour votre langue cible. En Perl, ceci est connu comme if $running_under_some_shell .

 #!/bin/sh eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}' if $running_under_some_shell; use … 

Voici une façon d'get le même effet en Python. Dans le shell, "true" est l'utilitaire true , qui ignore ses arguments (deux strings de caractère simple : et ' ) et renvoie une valeur vraie. En Python, "true" est une string qui est vraie quand elle est interprétée comme un boolean, donc c'est une instruction qui est toujours vraie et qui exécute une string littérale.

 #!/bin/sh if "true" : '''\' then exec "$FOO/bar/MyCustomPython" "$0" "$@" exit 127 fi ''' import … 

Le code Rosetta a de tels scripts en deux langues dans plusieurs autres langues.

Les lignes Shebang ne subissent pas d'expansion variable, vous ne pouvez donc pas utiliser $FOO/MyCustomPython car il searchrait un exécutable nommé dollar-FOO -…

Une alternative consiste à faire pointer votre script vers un script shell en tant qu'interprète et ce script shell peut ensuite utiliser des variables d'environnement pour localiser le script correct et l'exécuter.

Exemple: créez un script mypython.sh dans /usr/local/bin (ou tout autre directory de votre $PATH ), avec le contenu suivant:

 #! /bin/sh PYTHON="$FOO/bar/MyCustomPython" exec "$PYTHON" "$@" 

alors vous pouvez utiliser cette ligne shebang pour qu'un script Python soit exécuté via MyCustomPython via mypython.sh :

 #!/usr/bin/env mypython.sh 

Vous pouvez soit utiliser le path absolu vers l'installation personnalisée de python, soit la mettre dans votre $PATH et utiliser la command #!/usr/bin/env [command] . Sinon, écrivez un wrapper et utilisez exec pour replace l'image du process, par exemple:

 #!/bin/bash exec "$ENV/python" "$@" 

Tout d'abord, déterminez comment votre version de Python est différente du Python standard déjà installé (par exemple, un module supplémentaire), puis au début du programme, changez la façon dont le Python est appelé:

 #!/usr/bin/python import os import sys try: import MyCustomModule except ImportError: # only need to use expandvar if you know the ssortingng below has an envvar custprog = os.path.expandvar("$FOO/bar/MyCustomPython") os.execv(custprog, sys.argv) # call alternate python with the same arguments raise SystemExit('could not call %s' % custprog) # if we get here, then we have the correct python interpreter 

Cela devrait permettre au programme d'être appelé par toute autre instance de Python. Je fais quelque chose de similaire pour une instance avec une bibliothèque sql embeddede qui ne peut pas être imscope en tant que module dans le python du système.

Si vous pouvez replace $FOO dans $FOO/bar/MyCustomPython par des options de path concrètes, vous pouvez indiquer à la ligne env shebang où chercher votre version personnalisée de Python en définissant directement un PATH personnalisé.

 #!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python 

Edit : Semble fonctionner seulement sans guillemets autour de l'affectation de la valeur PATH:

 #!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python