Как получить переменные окружения подпроцесса после его завершения? - PullRequest
2 голосов
/ 06 мая 2011

Я ищу способ сделать это, чтобы я мог передать его в среду другого подпроцесса.

Ответы [ 4 ]

4 голосов
/ 16 декабря 2016

Вот простая функция, которая запускает команду в подпроцессе, а затем извлекает его окружение в текущий процесс.

Он основан на версии Fnord, без временного файла и с маркерной линией, чтобы отличить команду SET от любого вывода самого процесса.Это не пуленепробиваемый, но он работает для моих целей.

def setenv(cmd):
    cmd = cmd + ' && echo ~~~~START_ENVIRONMENT_HERE~~~~ && set'

    env = (subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
                     .stdout
                     .read()
                     .decode('utf-8')
                     .splitlines())

    record = False
    for e in env:
        if record:
            e = e.strip().split('=')
            os.environ[e[0]] = e[1]
        elif e.strip() == '~~~~START_ENVIRONMENT_HERE~~~~': 
            record = True
4 голосов
/ 06 мая 2011

К сожалению, дочерняя среда испарится, как только она выйдет, и даже если вы используете файловую систему / proc в Unix специальный файл /proc/[pid]/environ, она не будет отражать изменения, сделанные дочерним процессом.

Даже если вышеперечисленное сработало, у вас возникло бы условие гонки: родитель должен был бы определить «правильное время» для чтения окружения, в идеале сразу после того, как ребенок изменил его.Чтобы сделать это, родитель должен координировать свои действия с ребенком, и пока вы координируете, вы также можете явно общаться.

Вам нужно будет передавать состояние между родителем и дочерним элементом через сокет,конвейер, разделяемая память и т. д. многопроцессорный модуль *1009* может сделать это немного проще, позволяя передавать данные от дочернего к родительскому через очереди или каналы.

Обновлено Воткраткий обзор использования модуля multiprocessing, чтобы позволить родительскому процессу обмениваться значениями с дочерними процессами, а дочерним процессам связываться друг с другом через очередь.Это довольно просто:

import os
from multiprocessing import Process, Manager, Queue

def worker1(d, q):
    # receive value from worker2
    msg = q.get()
    d['value'] += 1
    d['worker1'] = os.getpid(), msg

def worker2(d, q):
    # send value to worker1
    q.put('hi from worker2')
    d['value'] += 1
    d['worker2'] = os.getpid()

if __name__ == '__main__':
    mgr = Manager()
    d = mgr.dict()
    q = Queue()
    d['value'] = 1
    p1 = Process(target=worker1, args=(d,q))
    p1.start()
    p2 = Process(target=worker2, args=(d,q))
    p2.start()
    p1.join()
    p2.join()
    print d

Результат:

{'worker1': (47395, 'hi from worker2'), 'worker2': 47396, 'value': 3}
2 голосов
/ 18 октября 2013

В Windows вы можете использовать команду SET , чтобы получить то, что вы хотите, например:

import os, tempfile, subprocess

def set_env(bat_file):
    ''' Set current os.environ variables by sourcing an existing .bat file
        Note that because of a bug with stdout=subprocess.PIPE in my environment
        i use '>' to pipe out the output of 'set' into a text file, instead of
        of using stdout. So you could simplify this a bit...
    '''

    # Run the command and pipe to a tempfile
    temp = tempfile.mktemp()
    cmd = '%s && set > %s'%(bat_file,temp)
    login = subprocess.Popen(cmd, shell=True)
    state = login.wait()

    # Parse the output
    data = []
    if os.path.isfile(temp):
        with open(temp,'r') as file:
            data = file.readlines()
        os.remove(temp)

    # Every line will set an env variable
    for env in data:
        env = env.strip().split('=')
        os.environ[env[0]] = env[1]


# Make an environment variable
os.environ['SOME_AWESOME_VARIABLE']='nothing'

# Run a batch file which you expect, amongst other things, to change this env variable
set_env('C:/do_something_awesome.bat')

# Lets see what happened
os.environ['SOME_AWESOME_VARIABLE']
// RESULT: 'AWESOME'

Так что теперь, если вы можете использовать это для чтения файлов .bat, а затем использоватьпеременные окружения, которые он генерирует по своему усмотрению, изменяйте / добавляйте к ним, переходите к новому процессу ... и т. д. *

1 голос
/ 06 мая 2011

Можете ли вы распечатать их в первом подпроцессе и разобраться с этой строкой в ​​python?

...