在Python multiprocessing.Process中设置env var

时间:2014-07-08 22:57:24

标签: python environment-variables multiprocessing

subprocess Python 2模块中,Popen可以获得env

似乎在Process模块中使用multiprocessing执行此操作的等效方法是在envargs中传递kwargs字典,然后使用os.environ['FOO'] = value中的target

这是正确的方法吗?

安全吗?我的意思是,没有风险可以修改父进程或其他子进程中的环境吗?

这是一个例子(有效)。

import multiprocessing
import time
import os

def target(someid):
    os.environ['FOO'] = "foo%i" % someid
    for i in range(10):
        print "Job %i: " % someid, os.environ['FOO']
        time.sleep(1)

if __name__ == '__main__':

    processes = []

    os.environ['FOO'] = 'foo'

    for someid in range(3):
        p = multiprocessing.Process(target=target, args=(someid,))
        p.start()
        processes.append(p)

    for i in range(10):
        print "Parent: ", os.environ['FOO']
        time.sleep(1)

    for p in processes:
        p.join()

1 个答案:

答案 0 :(得分:16)

是的,这是正确的方法。虽然孩子将从父母继承其初始环境,但孩子对os.environ的后续更改不会影响父母,反之亦然:

import os
import multiprocessing


def myfunc(q):
    print "child: " + os.environ['FOO']
    os.environ['FOO'] = "child_set"
    print "child new: " + os.environ['FOO']
    q.put(None)
    q.get()
    print "child new2: " + os.environ['FOO']


if __name__ == "__main__":
    os.environ['FOO'] = 'parent_set'
    q = multiprocessing.Queue()
    proc = multiprocessing.Process(target=myfunc, args=(q,))
    proc.start()
    q.get()
    print "parent: " + os.environ['FOO']
    os.environ['FOO'] = "parent_set_again"
    q.put(None)

输出:

child start: parent_set
child after changing: child_set
parent after child changing: parent_set
child after parent changing: child_set

如果您需要将初始环境传递给孩子,您只需将其传递到argskwargs列表中:

def myfunc(env=None):
    time.sleep(3)
    if env is not None:
        os.environ = env
    print os.environ['FOO']


if __name__ == "__main__":
    child_env = os.environ.copy()

    for i in range(3):
        child_env['FOO'] = "foo%s" % (i,)
        proc = multiprocessing.Process(target=myfunc, kwargs ={'env' : child_env})
        proc.start()

输出:

foo0
foo1
foo2

请注意,如果您使用multiprocessing.Pool,则可以使用initializer / initargs关键字参数在每个流程开始时设置一次正确的环境游泳池:

def init(env):
    os.environ = env

def myfunc():
    print os.environ['FOO']


if __name__ == "__main__":
    child_env = os.environ.copy()
    child_env['FOO'] = "foo"
    pool = multiprocessing.Pool(initializer=init, initargs=(child_env,))
    pool.apply(myfunc,()) 

输出:

foo