有關python3的multiprocessing.Pool.map問題,發生錯誤??

from multiprocessing import Pool

def f(x):

return x*x

pool = Pool(processes=4)

r=pool.map(f, range(100))

pool.close()

pool.join()

在spyder里運行直接沒反應;在shell窗口裡,直接報錯,如下:

Process SpawnPoolWorker-15:

Traceback (most recent call last):

File "C:Anaconda3libmultiprocessingprocess.py", line 254, in _bootstr

self.run()

File "C:Anaconda3libmultiprocessingprocess.py", line 93, in run

self._target(*self._args, **self._kwargs)

File "C:Anaconda3libmultiprocessingpool.py", line 108, in worker

task = get()

File "C:Anaconda3libmultiprocessingqueues.py", line 357, in get

return ForkingPickler.loads(res)

AttributeError: Can"t get attribute "f" on &

這是咋么回事


Windows下面的multiprocessing跟Linux下面略有不同,Linux下面基於fork,fork之後所有的本地變數都複製一份,因此可以使用任意的全局變數;在Windows下面,多進程是通過啟動新進程完成的,所有的全局變數都是重新初始化的,在運行過程中動態生成、修改過的全局變數是不能使用的。

multiprocessing內部使用pickling傳遞map的參數到不同的進程,當傳遞一個函數或類時,pickling將函數或者類用所在模塊+函數/類名的方式表示,如果對端的Python進程無法在對應的模塊中找到相應的函數或者類,就會出錯。當你在Interactive Console當中創建函數的時候,這個函數是動態添加到__main__模塊中的,在重新啟動的新進程當中不存在,所以會出錯。

當不在Console中,而是在獨立Python文件中運行時,你會遇到另一個問題:

由於你下面調用multiprocessing的代碼沒有保護,在新進程載入這個模塊的時候會重新執行這段代碼,創建出新的multiprocessing池,無限調用下去。解決這個問題的方法是永遠把實際執行功能的代碼加入到帶保護的區域中:

from multiprocessing import Pool
def f(x):
return x*x

if __name__ == "__main__":
pool = Pool(processes=4)
r=pool.map(f, range(100))
pool.close()
pool.join()

注意if __name__ == "__main__"這一行,當模塊從import當中載入的時候這行保證下面的代碼不會執行。


用標準python 試試,不要用Anaconda 安裝的python3


Pool不能在__main__那個名字空間里用。把它封進一個函數里就行了,像這樣:

def f(x):
return x**2
def shell():
pool=Pool(4)
r=pool.map(f,range(10))
pool.close()
pool.join()
return r


你好,題主。我也遇到了跟你一樣類似的問題。不知最後有無完美的解決方案?

我用的是Anaconda,IDE也是spyder。


推薦閱讀:

動態類型的語言的優缺點有哪些?
python shell代碼無法保存為何?
python 中 os._exit(), sys.exit(), exit() 的區別是什麼?
Python3.3和Python3.2的區別在哪裡?
為什麼在Python定義函數中想使用return語句返回一個list卻沒有任何返回值?

TAG:Python | Python3x | Python入門 |