J'ai un script Python qui doit être exécuté avec une installation Python particulière. Y a-t-il un moyen de fabriquer un shebang pour qu'il fonctionne avec $FOO/bar/MyCustomPython
?
J'ai un script Python qui doit être exécuté avec une installation Python particulière. Y a-t-il un moyen de fabriquer un shebang pour qu'il fonctionne avec $FOO/bar/MyCustomPython
?
Réponses:
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 commande et un seul argument. Il y a aussi souvent une limitation de longueur.
La solution générale consiste à écrire un petit wrapper shell. Nommez le script Python foo.py
, mettez le script shell à côté 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 consiste à écrire un script wrapper similaire à celui ci-dessus et à l'insérer #!/path/to/wrapper/script
comme ligne shebang dans le script Python. Cependant, la plupart des ordinateurs ne supportent pas l'enchaînement de scripts shebang, donc cela ne fonctionnera pas.
Si MyCustomPython
était dans le $PATH
, vous pouvez utiliser env
pour le rechercher:
#!/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 le langage cible (ici Python). Cela nécessite que vous trouviez un moyen d'écrire un tel script bilingue pour votre langue cible. En Perl, cela s'appelle if $running_under_some_shell
.
#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
if $running_under_some_shell;
use …
Voici un moyen d'obtenir le même effet en Python. Dans le shell, "true"
c'est l' true
utilitaire qui ignore ses arguments (deux chaînes à caractère unique :
et '
) et renvoie une valeur true. En Python, "true"
est une chaîne qui est vraie lorsqu'elle est interprétée comme un booléen. Il s'agit donc d'une if
instruction toujours vraie et qui exécute un littéral de chaîne.
#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …
Le code Rosetta a de tels scripts bilingues dans plusieurs autres langues.
PYTHONPATH
variable env afin de charger des modules à partir d'un emplacement non standard pour un script CGI sur un système auquel je n'avais pas accès root. Épargnant de vie. Merci encore.
Les lignes Shebang ne subissent pas de développement variable, vous ne pouvez donc pas utiliser $FOO/MyCustomPython
car elles rechercheraient un exécutable nommé dollar-FOO -...
Une alternative consiste à faire pointer votre shebang sur un script shell en tant qu'interprète, qui peut ensuite utiliser des variables d'environnement pour localiser le correct et l'exécuter.
Exemple: créez un mypython.sh
script dans /usr/local/bin
(ou tout autre répertoire de votre $PATH
), avec le contenu suivant:
#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"
alors vous pouvez utiliser cette ligne shebang pour faire exécuter un script Python MyCustomPython
via mypython.sh
:
#!/usr/bin/env mypython.sh
$python
, non pas $PYTHON
- par convention, nous capitalisons les variables d’environnement (PAGER, EDITOR, SHELL ... $PYTHON
dans votre script n’est pas une variable d’environnement) et les variables d’enveloppe internes (BASH_VERSION, RANDOM, ...). Tous les autres noms de variables doivent contenir au moins une lettre minuscule. Cette convention évite de passer outre aux variables environnementales et internes accidentellement. De plus, n'utilisez pas d'extensions pour vos scripts. Les scripts définissent de nouvelles commandes que vous pouvez exécuter et les commandes ne reçoivent généralement pas d'extensions.
Vous pouvez soit utiliser le chemin absolu de l’installation python personnalisée, soit le placer dans votre $PATH
et l’utiliser #!/usr/bin/env [command]
. Sinon, écrivez un wrapper pour cela et utilisez-le exec
pour remplacer l'image de processus, à titre d'exemple:
#!/bin/bash
exec "$ENV/python" "$@"
Tout d'abord, déterminez en quoi votre version de Python est différente de la version standard de Python déjà installée (par exemple, un module supplémentaire), puis au début du programme 'switch', comment s'appelle Python:
#!/usr/bin/python
import os
import sys
try:
import MyCustomModule
except ImportError:
# only need to use expandvar if you know the string 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 la bibliothèque SQL intégrée qui ne peut pas être importée en tant que module dans le python du système.
Si vous pouvez remplacer $FOO
dans $FOO/bar/MyCustomPython
des options de chemin en béton, vous pouvez dire à la env
ligne tralala où rechercher en mettant directement votre version Python personnalisé une coutume PATH
en elle.
#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python
Edit : semble fonctionner uniquement sans guillemets autour de l'attribution de valeur PATH:
#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
PATH
comme ceci:PATH=$PATH:/path/to/whatever...