2017-07-11 21 views
0

我遇到了Python的多,我无法理解的一些行为......在Python中,如果我将一个普通变量传递给一个函数并使用apply_async在多个进程中执行它,会发生什么?

例如:

from multiprocessing import Pool 
import time 
import sys 

def f(x): 
    time.sleep(10) 
    print(x) 
    return x * x 

def f2(x, f): 
    time.sleep(10) 
    print(x, file=f) 
    return x * x 

if __name__ == '__main__': 
    p = Pool(5) 
    for t in range(10): 
     p.apply_async(f, args=(t,)) 
    p.close() 
    p.join() # Here it blocks and prints the number, which is normal. 

    p = Pool(5) 
    for t in range(10): 
     p.apply_async(f2, args=(t, sys.stdout)) 
    p.close() 
    p.join() # Here it does not block and nothing happends(no output at all)... 

输出是:

3 
1 
0 
2 
4 
5 
9 
6 
7 
8 

我知道,我们必须使用类似共享变量传递给函数时使用多处理和apply_async,但如果我将一个正常变量传递给apply_async中使用的函数会发生什么?

回答

0

multiprocessing.Pool在单独的过程中执行您的逻辑。如果逻辑引发异常,则Pool将把它返回给调用者。

在你的代码中,你没有收集你的函数的输出,因此你没有注意到真正的问题。

尝试如下修改代码:

p = Pool(5) 
    for t in range(10): 
     task = p.apply_async(f2, args=(t, sys.stdout)) 
     task.get() 

你会再拿到这是内f2提出了实际的异常:

Traceback (most recent call last): 
    File "asd.py", line 24, in <module> 
    p.apply_async(f2, args=(t, sys.stdout)).get() 
    File "/usr/lib/python3.5/multiprocessing/pool.py", line 608, in get 
    raise self._value 
    File "/usr/lib/python3.5/multiprocessing/pool.py", line 385, in _handle_tasks 
    put(task) 
    File "/usr/lib/python3.5/multiprocessing/connection.py", line 206, in send 
    self._send_bytes(ForkingPickler.dumps(obj)) 
    File "/usr/lib/python3.5/multiprocessing/reduction.py", line 50, in dumps 
    cls(buf, protocol).dump(obj) 
TypeError: cannot serialize '_io.TextIOWrapper' object 

事实证明,sys.stdoutpicklable。在这种情况下,哪一个过程不是唯一的问题,因为sys.stdout是唯一的。您可以避免将它传递给函数,只需在f2之内使用它。

相关问题