comment faire des sous-processus appelé avec appel/Popen hériter des variables d'environnement
Tout d'abord, toutes mes excuses pour ce que je suis sûr qu'ils vont être évident est ma compréhension rudimentaire de bash et de coquilles et de sous-processus.
Je suis en train d'utiliser Python pour automatiser les appels à un programme appelé Freesurfer (en fait, je vais appeler le sous-programme est appelé recon-all.)
Si je faisais ça directement à la ligne de commande, je serais "source" d'un script appelé mySetUpFreeSurfer.sh cela ne fait rien, mais de définir trois variables d'environnement, puis "source" d'un autre script, FreeSurferEnv.sh. FreesurferEnv.sh ne semble pas à moi de faire quelque chose, mais mis beaucoup de variables de l'environnement et de l'écho des trucs à la borne, mais c'est plus compliqué que les autres script bash, donc je ne suis pas sûr de ce que.
Voici ce que j'ai en ce moment:
from subprocess import Popen, PIPE, call, check_output
import os
root = "/media/foo/"
#I got this function from another Stack Overflow question.
def source(script, update=1):
pipe = Popen(". %s; env" % script, stdout=PIPE, shell=True)
data = pipe.communicate()[0]
env = dict((line.split("=", 1) for line in data.splitlines()))
if update:
os.environ.update(env)
return env
source('~/scripts/mySetUpFreeSurfer.sh')
source('/usr/local/freesurfer/FreeSurferEnv.sh')
for sub_dir in os.listdir(root):
sub = "s" + sub_dir[0:4]
anat_dir = os.path.join(root, sub_dir, "anatomical")
for directory in os.listdir(anat_dir):
time_dir = os.path.join(anat_dir, directory)
for d in os.listdir(time_dir):
dicoms_dir = os.path.join(time_dir, d, 'dicoms')
dicom_list = os.listdir(dicoms_dir)
dicom = dicom_list[0]
path = os.path.join(dicoms_dir, dicom)
cmd1 = "recon-all -i " + path + " -subjid " + sub
check_output(cmd1, shell=True)
call(cmd1, shell=True)
cmd2 = "recon-all -all -subjid " + sub,
call(cmd2, shell=True)
C'est un échec:
Traceback (most recent call last):
File "/home/katie/scripts/autoReconSO.py", line 28, in <module>
check_output(cmd1, shell=True)
File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'recon-all -i /media/foo/bar -subjid s1001' returned non-zero exit status 127
J'ai peut-être comprendre pourquoi il en est. Mon "appels", plus loin dans le script sont la collecte de nouveaux sous-processus qui n'héritent pas des variables d'environnement du processus qui sont soulevées par l'invocation de la source (le) de la fonction. J'ai fait un certain nombre de choses pour essayer de confirmer ma compréhension. Un exemple -- j'ai mis ces lignes:
mkdir ~/testFreeSurferEnv
export TEST_ENV_VAR=~/testFreeSurferEnv
dans le FreeSurferEnv.sh script. Le répertoire obtient fait très bien, mais dans le script Python ceci:
cmd = 'mkdir $TEST_ENV_VAR/test'
check_output(cmd, shell=True)
échoue comme ceci:
File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'mkdir $TEST_ENV_VAR/test' returned non-zero exit status 1
QUESTION:
Comment puis-je faire de la sous-processus qui s'exécute "recon" héritent les variables d'environnement dont il a besoin? Ou comment je peux faire tout ce que je dois faire -- exécuter les scripts pour définir les variables d'environnement, et de l'appeler recon-tout, dans le même processus? Ou devrais-je aborder le problème d'une autre façon? Ou dois-je probablement mal compris le problème?
OriginalL'auteur Katie | 2013-12-18
Vous devez vous connecter pour publier un commentaire.
Concernant
Je pense que vous feriez mieux d'utiliser Python pour automatiser le processus de l'écriture
un script shell
newscript.sh
, puis d'appeler ce script avec un appelsubprocess.check_output
(au lieu de plusieurs appels àPopen
,check_output
,call
, etc.):newscript.sh:
et puis l'appel de
Par la voie,
est cassé. Par exemple, si
script
contient quelque chose commepuis
peut-retour de sortie comme
qui entraînera
source(script)
élever unValueError
:Il y a un moyen de corriger
source
: ontenv
séparer les variables d'environnement avec un zéro octet au lieu de l'ambiguïté de la nouvelle ligne:Réparable ou non, cependant, vous êtes probablement mieux de la construction d'un
conglomérat script shell (comme illustré ci-dessus) que vous seriez d'analyse
env
eten passant
env
dicts àsubprocess
appels.Cela fonctionnait très bien, merci beaucoup! Je vais rappeler l'astuce d'utiliser Python pour écrire un simple script bash pour toujours, et j'ai aussi appris quelques nouveaux Python de votre réponse. Peut-être vous devriez noter la façon dont cette fonction de la source est cassé ici: stackoverflow.com/a/12708396/2066083 ? C'est là que je l'ai eu.
OriginalL'auteur unutbu
Si vous regardez la documentation pour
Popen
, il prend unenv
paramètre:Vous ai écrit une fonction qui extrait l'environnement que vous voulez à partir de votre source des scripts et le met dans un
dict
. Il suffit de passer le résultat que l'env
pour les scripts que vous souhaitez utiliser. Par exemple:Il y a d'autres raisons
mkdir
pourrait être défectueux. Si vous essayez d'exécutercheck_output('echo $TEST_ENV_VAR/test', shell=True, env=env)
, voulez-vous revenir~/testFreeSurferEnv/test
, ou aussi échouer? Quand j'ai essayer le test (la définition explicite deenv['TEST_ENV_VAR']
au lieu de passer par tous vos autres code, parce que vous vous dites tous ce que les autres code fonctionne) sur OS X et Linux avec Python 2.7 et 3.3 ou 3.4, il fonctionne dans tous les cas.Ce n'est pas un échec. Je pense que j'ai été enclin à penser que mon problème a été résolu parce que la nuit dernière, quand j'ai essayé à l'aide de la source en fonction de la façon correcte, la recon-toute commande est également toujours à la peine avec la sortie d'état 127. Malheureusement, je ne peux pas vraiment enquêter sur ce droit maintenant, parce que j'ai utilisé la fonction "utiliser Python pour écrire un simple script bash" méthode suggérée par unutbu de commencer mon travail, et de la modification des variables d'environnement à ce point pourrait causer des ravages. Je suis curieux de comprendre les sous-jacents situation meilleure, mais atm-je le laisser seul. J'apprécie vraiment l'aider.
Il n'y a pas de moyen direct d'extraire toutes les variables d'environnement à partir d'un sous-processus? La proposition de @unutbu est assez décent, mais je voudrais bien que il a été construit.
C'est une limitation de la conception du système (Unix et Windows NT).
OriginalL'auteur abarnert