Comment obtenir PID via un processus secondaire.Popen à la coutume de la variable d'environnement?
À l'aide de Python, comment puis-je exécuter un sous-processus avec une modification de la variable d'environnement et d'obtenir son PID? Je suppose sous-processus.Popen() est sur la bonne voie...
Dans le shell (bash), je voudrais faire cela:
MY_ENV_VAR=value ./program_name arg1 arg2 etc &
Cela va program_name
en arrière-plan, en passant "arg1" et "arg2" et le "etc", avec une modification de la variable d'environnement "MY_ENV_VAR" avec une valeur de "valeur". Le programme program_name
nécessite la variable d'environnement MY_ENV_VAR
à être fixé à la valeur correcte.
Comment faire l'équivalent chose en Python? J'ai absolument besoin de le PID du processus. (Mon intention est de garder le script python, l'exécution et la réalisation des vérifications sur certaines choses program_name
est fait dans le temps, et j'ai besoin de l'ID de processus pour s'assurer qu'il est toujours en cours d'exécution.)
J'ai essayé:
proc = subprocess.Popen(['MY_ENV_VAR=value', './program_name', 'arg1', 'arg2', 'etc'])
Mais bien sûr, il attend le premier élément à être le programme, pas une variable d'environnement.
Aussi essayé:
environ = dict(os.environ)
environ['MY_ENV_VAR'] = 'value'
proc = subprocess.Popen(['./program_name', 'arg1', 'arg2', 'etc', env=environ])
Près, je suppose, mais pas de cigare. De même, ce:
environ = dict(os.environ)
environ['MY_ENV_VAR'] = 'value'
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ)
Cela fait écho à "$MY_ENV_VAR" littéralement, je suppose, parce que il n'y a pas de shell pour l'interpréter. Ok, alors je vais essayer ci-dessus, mais avec cette ligne à la place:
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ, shell=True)
Et c'est très bien et dandy, sauf que la valeur de l'écho est vide (n'existent apparemment). Et même si elle a fait un travail, je voudrais obtenir le PID du shell, et non le processus réel, je suis en train de lancer.
J'ai besoin de lancer un processus avec une mesure de la variable d'environnement et d'obtenir son PID (pas le PID du shell). Des idées?
J'ai seulement besoin de la coque, dans la mesure où le paramètre de configuration/en passant la variable d'environnement pour que le processus continue. Si je n'ai pas besoin de la coquille, je préfère ne pas l'utiliser. (Mais je n'ai besoin de passer des arguments au programme et l'exécuter en arrière-plan.)
Les variables d'environnement qui sont passés à la sous-processus dans votre
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ)
exemple; que les sous-processus n'est pas simplement faire quelque chose pour vous montrer qu'ils sont, parce que l'écho ne regarde jamais à son environnement. Essayez subprocess.Popen(['env'], env=environ)
à la place.Oh pinaise! C'est tout. Vous et abarnet eu pour moi à la même époque.
Par ailleurs, si vous avez besoin du "réel" du programme PID lors de l'utilisation de
shell=True
(qui, encore une fois, vous ne devriez jamais utiliser à moins que vous vraiment savez ce que vous faites), vous pouvez le faire en ayant le script shell invoquer la commande finale avec exec
. Pour cet exemple: exec echo "$MY_ENV_VAR"
; ce faisant, il entraînera la commande echo pour remplacer le shell en cours d'exécution du processus, héritant de son PID.OriginalL'auteur Matt | 2013-04-03
Vous devez vous connecter pour publier un commentaire.
Votre dernière version est très proche, mais pas tout à fait là.
Vous ne voulez pas
$MY_ENV_VAR
être un argument pourecho
. Leecho
programme auraMY_ENV_VAR
dans son environnement, maisecho
ne fait pas env extension variable. Vous avez besoin d'être élargi par le shell, avant même qu'elle arrive àecho
.Cela peut effectivement n'ont rien à voir avec la vraie vie, de cas de test. Vous avez déjà sont l'obtention de la variable d'environnement pour le processus de l'enfant dans l'ensemble de vos tests, c'est juste que
echo
ne pas faire n'importe quoi avec cette variable d'environnement. Si votre programme a juste besoin de la variable d'environnement à définir, vous avez terminé:Mais si votre programme a besoin d'elle pour être substitué, comme
echo
, alors vous devez le remplacer dans les arguments avant ils sont passés à votre programme.La façon la plus simple de le faire est de simplement donner le shell de ligne de commande au lieu d'une liste d'arguments:
Gens vont vous dire que vous ne devez jamais utiliser une chaîne de commande dans
subprocess
—, mais la raison est que vous voulez toujours pour éviter que le shell développant des variables, etc., d'une façon qui pourrait être précaire, etc. Dans les rares occasions où vous voulez la coque pour faire son shelly choses, vous voulez une chaîne de commande.Bien sûr, si vous utilisez un shell, sur la plupart des plates-formes, vous allez finir par avoir le PID du shell plutôt que de le PID du programme. Court de faire de certains de la plate-forme de creuser pour énumérer de l'environnement des enfants (ou en l'enveloppant le tout dans une simple
sh
code qui vous donne de l'enfant PID indirectement), il n'y a pas moyen de contourner cela. La coquille est ce que vous êtes en cours d'exécution.Une autre alternative est de développer les variables en Python au lieu de faire de la coquille de le faire. Ensuite, vous n'avez même pas besoin un shell:
... ou, plus simplement encore:
'echo "$MY_ENV_VAR"'
, s'il vous plait, sinon, la variable le contenu de la chaîne-split et glob-élargi.Cool, que (le premier) fonctionne, et je comprends maintenant pourquoi, mais je reçois le PID du shell (sh) au lieu de l'écho des processus. Comme pour l'expansion de la variable avec Python, c'est une excellente idée, mais je n'était probablement pas clair: le programme qui l'appelle s'attend à ce que variable d'environnement pour être ensemble, je ne peux pas juste passer comme un argument.
Vous pourriez être la lecture d'une version antérieure de la réponse. Pour obtenir la variable d'environnement set plutôt que substitué, il suffit d'utiliser la
env
paramètre, et ne pas utiliser le shell. La seule raison pour laquelle cela ne fonctionne pas dans votreecho
tests est que l'écho des besoins de la variable substitué, non défini.Vous avez raison. Je me suis mise à jour de votre réponse et de Charles le commentaire en même temps. Cela semble faire l'affaire. Merci! Je ne savais pas que l'environnement a été passée directement au programme au lieu d'un shell (duh, de ma part).
OriginalL'auteur abarnert
voici un programme qui crache de l'environnement actuel.
Voici un programme qui appelle l'autre programme, mais le premier changement de l'environnement
{k:v for k,v in anything.iteritems()}
au lieu de simplementdict(anything)
?Je ne pensais pas à travers.
OriginalL'auteur Hal Canary