2009-07-31 6 views
14

Ich möchte einen Prozess über ein Python-Programm aufrufen, jedoch benötigt dieser Prozess einige bestimmte Umgebungsvariablen, die von einem anderen Prozess festgelegt werden. Wie kann ich die ersten Prozessumgebungsvariablen erhalten, um sie an die zweite zu übergeben?So erhalten Sie Umgebung von einem Subprozess in Python

Dies ist, was das Programm wie folgt aussehen:

import subprocess 

subprocess.call(['proc1']) # this set env. variables for proc2 
subprocess.call(['proc2']) # this must have env. variables set by proc1 to work 

aber die die gleiche Umgebung nicht teilen zu verarbeiten. Beachten Sie, dass diese Programme nicht meins sind (das erste ist eine große und hässliche .bat-Datei und das zweite ein proprietäres Soft), so dass ich sie nicht modifizieren kann (ok, ich kann alles aus der .bat extrahieren, aber es ist sehr komerziös).

NB: ich Windows verwende, aber ich ziehe es eine Cross-Plattform-Lösung (aber mein Problem auf einem Unix-artigen nicht passieren würde ...)

+0

Eine .bat Datei? Wenn Sie in Windows laufen, sollten Sie es wirklich deutlich sagen. –

Antwort

2

Da Sie offenbar in Windows sind, müssen Sie ein Windows Antwort.

Erstellen Sie eine Wrapper-Batchdatei, z. „Run_program.bat“, und laufen beide Programme:

@echo off 
call proc1.bat 
proc2 

Das Skript wird seine Umgebungsvariablen ausgeführt und eingestellt. Beide Skripte laufen im selben Interpreter (cmd.exe-Instanz), so wird die Variable prog1.bat gesetzt wird gesetzt werden, wenn prog2 ausgeführt wird.

Nicht besonders schön, aber es wird funktionieren.

(Unix Menschen, können Sie die gleiche Sache in einem Bash-Skript tun. „Quelle file.sh“)

+0

Ich versuche speziell mit 'Sourch blah; now_do_second_thing' – nmz787

4

Wie Sie sagen, Prozesse teilen nicht die Umgebung - also was Sie buchstäblich fragen ist nicht möglich, nicht nur in Python, sondern mit jeder Programmiersprache.

Was Sie können tun ist, um die Umgebungsvariablen in einer Datei zu setzen, oder in einem Rohr, und entweder

  • haben der übergeordnete Prozess lesen sie und geben sie nicht an proc2 vor proc2 erstellt wird, oder
  • haben sie proc2 zu lesen und stellt sie vor Ort

Letzteres würde die Zusammenarbeit von proc2 erfordern; Ersteres erfordert, dass die Variablen bekannt werden, bevor proc2 gestartet wird.

+0

Wenn Sie unter Linux root sind, können Sie/proc//environ überprüfen und analysieren ... nicht "unmöglich". – 0x6adb015

+0

@ 0x6abd015: Dies ist jedoch nicht das, was das OP fragt: Er will nicht, dass proc2 herausfindet, was die Umgebung von proc1 ist (was man mit dem proc-Dateisystem tun kann), aber er will proc1 * set * -Umgebung für proc2 - Ich behaupte immer noch, dass dies unmöglich ist. –

0

Die Umgebung wird vom übergeordneten Prozess geerbt. Legen Sie im Hauptskript die von Ihnen benötigte Umgebung und keinen Unterprozess (untergeordnet) fest.

+0

Dies beantwortet die Frage nicht. Es gibt gute Gründe, dies auch nicht zu tun, wenn Sie Programme haben, die beispielsweise widersprüchliche ENV-Werte benötigen. – nmz787

0

Zwei Dinge fallen in den Sinn: (1) die Prozesse teilen die gleiche Umgebung, indem sie irgendwie in den gleichen Prozess kombinieren, oder (2) den ersten Prozess produzieren Ausgabe, die die relevanten Umgebungsvariablen, so Python enthält kann es lesen und die Umgebung für den zweiten Prozess konstruieren. Ich denke (obwohl ich mir nicht 100% ig sicher bin), dass es keine Möglichkeit gibt, die Umgebung aus einem Subprozess zu holen, wie Sie es sich wünschen.

0

The Python standard module multiprocessing haben ein Queues-System, mit dem Sie ein pickle-fähiges Objekt übergeben können, das Prozesse durchlaufen soll. Auch Prozesse können Nachrichten (ein gebeiztes Objekt) mit os.pipe austauschen. Denken Sie daran, dass Ressourcen (z. B. Datenbankverbindung) und Handle (z. B. Dateihandles) nicht gebeizt werden können.

Sie auf diesen Link finden können interessant: Communication between processes with multiprocessing

Auch die PyMOTw über Multiprozessing erwähnenswert: multiprocessing Basics

sorry für meine Rechtschreibung

23

Hier ist ein Beispiel dafür, wie Sie Umgebungsvariablen aus einer Charge oder cmd-Datei extrahieren können ein ohne die Schaffung Wrapper-Skript. Genießen.

from __future__ import print_function 
import sys 
import subprocess 
import itertools 

def validate_pair(ob): 
    try: 
     if not (len(ob) == 2): 
      print("Unexpected result:", ob, file=sys.stderr) 
      raise ValueError 
    except: 
     return False 
    return True 

def consume(iter): 
    try: 
     while True: next(iter) 
    except StopIteration: 
     pass 

def get_environment_from_batch_command(env_cmd, initial=None): 
    """ 
    Take a command (either a single command or list of arguments) 
    and return the environment created after running that command. 
    Note that if the command must be a batch file or .cmd file, or the 
    changes to the environment will not be captured. 

    If initial is supplied, it is used as the initial environment passed 
    to the child process. 
    """ 
    if not isinstance(env_cmd, (list, tuple)): 
     env_cmd = [env_cmd] 
    # construct the command that will alter the environment 
    env_cmd = subprocess.list2cmdline(env_cmd) 
    # create a tag so we can tell in the output when the proc is done 
    tag = 'Done running command' 
    # construct a cmd.exe command to do accomplish this 
    cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars()) 
    # launch the process 
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial) 
    # parse the output sent to stdout 
    lines = proc.stdout 
    # consume whatever output occurs until the tag is reached 
    consume(itertools.takewhile(lambda l: tag not in l, lines)) 
    # define a way to handle each KEY=VALUE line 
    handle_line = lambda l: l.rstrip().split('=',1) 
    # parse key/values into pairs 
    pairs = map(handle_line, lines) 
    # make sure the pairs are valid 
    valid_pairs = filter(validate_pair, pairs) 
    # construct a dictionary of the pairs 
    result = dict(valid_pairs) 
    # let the process finish 
    proc.communicate() 
    return result 

So Ihre Frage zu beantworten, würden Sie eine Py-Datei erstellen, geschieht Folgendes:

env = get_environment_from_batch_command('proc1') 
subprocess.Popen('proc2', env=env) 
+0

Ein Edit schlug vor, dass die Implementierung wie geschrieben keine Nicht-ASCII-Codepages unterstützt. In diesem Fall wurde empfohlen, 'chcp 65001> NULL &&' vor '{env_cmd}' in der cmd-Konstruktion zu platzieren. –

+1

Hier ist eine aktualisierte Version dieser Funktion https://github.com/PySide/pyside2-setup/blob/master/utils.py#L379 –

+0

Dies ist nicht plattformübergreifend, wie OP angefordert. – nmz787

Verwandte Themen