J'ai un script qui ressemble à ceci:
export foo=/tmp/foo
export bar=/tmp/bar
Chaque fois que je construis, je lance «source init_env» (où init_env est le script ci-dessus) pour configurer certaines variables.
Pour accomplir la même chose en Python, j'avais ce code en cours d'exécution,
reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name = m.group('name')
value = ''
if m.group('value'):
value = m.group('value')
os.putenv(name, value)
Mais ensuite, quelqu'un a décidé que ce serait bien d'ajouter une ligne comme celle-ci au init_env
fichier:
export PATH="/foo/bar:/bar/foo:$PATH"
De toute évidence, mon script Python s'est effondré. Je pourrais modifier le script Python pour gérer cette ligne, mais cela se cassera plus tard lorsque quelqu'un proposera une nouvelle fonctionnalité à utiliser dans le init_env
fichier.
La question est de savoir s'il existe un moyen simple d'exécuter une commande Bash et de la laisser modifier mon os.environ
?
Réponses:
Le problème avec votre approche est que vous essayez d'interpréter des scripts bash. Essayez d'abord d'interpréter l'instruction d'exportation. Ensuite, vous remarquez que les gens utilisent l'expansion variable. Plus tard, les utilisateurs mettront des conditions dans leurs fichiers ou traiteront des substitutions. À la fin, vous aurez un interpréteur de script bash complet avec un milliard de bogues. Ne fais pas ça.
Laissez Bash interpréter le fichier pour vous, puis collectez les résultats.
Vous pouvez le faire comme ceci:
Assurez-vous que vous gérez les erreurs au cas où bash échouerait
source init_env
, ou bash lui-même échouerait à s'exécuter, ou le sous-processus échouerait à exécuter bash, ou toute autre erreur.le
env -i
au début de la ligne de commande crée un environnement propre. cela signifie que vous n'obtiendrez les variables d'environnement qu'à partir deinit_env
. si vous voulez l'environnement système hérité, omettezenv -i
.Lisez la documentation sur le sous-processus pour plus de détails.
Remarque: cela ne capturera que les variables définies avec l'
export
instruction, carenv
n'imprime que les variables exportées.Prendre plaisir.
Notez que la documentation Python indique que si vous souhaitez manipuler l'environnement, vous devez manipuler
os.environ
directement au lieu d'utiliseros.putenv()
. Je considère que c'est un bug, mais je m'éloigne du sujet.la source
proc.stdout()
donne des octets, donc j'obtenais unTypeError
online.partition()
. La conversion en chaîne aline.decode().partition("=")
résolu le problème.['env', '-i', 'bash', '-c', 'source .bashrc && env']
pour ne me donner que les variables d'environnement définies par le fichier rcUtilisation de cornichon:
Actualisé:
Cela utilise json, sous-processus et utilise explicitement / bin / bash (pour le support ubuntu):
la source
/bin/dash
, qui ne connaît pas lasource
commande. Pour l'utiliser sur Ubuntu, vous devez l'exécuter/bin/bash
explicitement, par exemple en utilisantpenv = subprocess.Popen(['/bin/bash', '-c', '%s && %s' %(source,dump)], stdout=subprocess.PIPE).stdout
(cela utilise lesubprocess
module le plus récent qui doit être importé).Plutôt que d'avoir votre script Python source dans le script bash, il serait plus simple et plus élégant d'avoir une source de script wrapper
init_env
, puis d'exécuter votre script Python avec l'environnement modifié.la source
bash --rcfile init_env -c ./script.py
Mise à jour de la réponse de @ lesmana pour Python 3. Notez l'utilisation de
env -i
qui empêche les variables d'environnement étrangères d'être définies / réinitialisées (potentiellement incorrectement étant donné le manque de gestion des variables d'environnement multilignes).la source
Exemple d'encapsulation de l'excellente réponse de @ Brian dans une fonction:
J'utilise cette fonction utilitaire pour lire les informations d'identification aws et les fichiers docker .env avec
include_unexported_variables=True
.la source