2014-10-09 59 views
4

所以我看了here,裝飾的功能不能被酸洗。事實上:爲什麼multiprocessing.Process能夠泡菜裝飾功能?

import multiprocessing as mp 

def deco(f): 
    def wrapper(*args, **kwargs): 
     try: 
      f(*args, **kwargs) 
     except: 
      print 'Exception caught!' 
    return wrapper 

@deco 
def f(x): 
    print x 
    raise OverflowError 

if __name__ == '__main__': 
    pool = mp.Pool(processes=1) 
    for _ in pool.imap_unordered(f, range(10)): 
     pass 
    pool.close() 
    pool.join() 
    print 'All done' 

日期:

Traceback (most recent call last): 
    File "deco0.py", line 19, in <module> 
    for _ in pool.imap_unordered(f, range(10)): 
    File "/Users/usualme/anaconda/lib/python2.7/multiprocessing/pool.py", line 659, in next 
    raise value 
cPickle.PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed 

但現在,如果我被Process更換map

import multiprocessing as mp 

def deco(f): 
    def wrapper(*args, **kwargs): 
     try: 
      f(*args, **kwargs) 
     except: 
      print 'Exception caught!' 
    return wrapper 

@deco 
def f(x): 
    print x 
    raise OverflowError 

if __name__ == '__main__': 
    p = mp.Process(target=f, args=(1,)) 
    p.start() 
    p.join() 
    print 'All done' 

日期:

1 
Exception caught! 
All done 

爲什麼工作?不需要醃製裝飾的功能嗎?

+1

'multiprocessing'使用'cPickle'在Python 2.x和'pickle':

import multiprocessing as mp def deco(f): def wrapper(*args, **kwargs): try: f(*args, **kwargs) except: print 'Exception caught!' return wrapper @deco def f(x): print x raise OverflowError if __name__ == '__main__': p = mp.Pool() p.apply(f, args=(1,)) # f needs to be pickled here. print 'All done' 

輸出。有一個'multiprocessing'的分支,它使用'dill'序列化程序...它可以醃製裝飾函數。這個名爲'pathos.multiprocessing'的fork只替換了序列化器...因此可以接受'Pool'和'Process'中的裝飾函數,並且可以在windows和linux上運行 - 也可以在解釋器中工作即使沒有從'__main__'調用'Pool'或'Process'。請參閱:https://github.com/uqfoundation。 – 2014-10-09 17:54:51

回答

2

它的工作原理是因爲你在Linux上運行,它不需要通過Process.__init__在子進程中調用f來調用它。這是因爲f由子女通過os.fork繼承。如果您在Windows上運行相同的代碼(缺少fork),或嘗試將f傳遞給Pool.apply/Pool/map(兩者都需要用f在子進程中調用它),那麼會出現錯誤。

這個例子將失敗,不管你用什麼樣的平臺:在3.X

1 
Exception caught! 
Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner 
    self.run() 
    File "/usr/lib/python2.7/threading.py", line 504, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "/usr/lib/python2.7/multiprocessing/pool.py", line 319, in _handle_tasks 
    put(task) 
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed