咨询个 Python 多进程中出现的奇怪问题

2017-07-03 17:41:39 +08:00
 raycool

直接上代码:

https://gist.github.com/raycool/aba7c1561d9e440351c2d2bff81a1a52

使用的 pycharm,windows7 64 位,这样不能出现结果,直接延迟 5 秒后就停止运行了。 偶然发现把 out 移到 class 外面就可以正常运行显示结果。

https://gist.github.com/raycool/cf3d1fa9d3dfb2fcca0fae2adfeddf0a

这样就可以正常运行,百思不得其解。求各位指点,到底第一个那样写代码有什么问题。

3176 次点击
所在节点    Python
10 条回复
raycool
2017-07-03 17:46:42 +08:00
raycool
2017-07-03 17:51:27 +08:00
为嘛主题上面不能显示代码。也不让在回复中连续插入代码。
wwqgtxx
2017-07-03 17:54:39 +08:00
可能是因为 Pool 不能跨进程传递,你试试
self.pool.apply_async(Data.out,(self, self.queue))
wwqgtxx
2017-07-03 18:14:40 +08:00
#coding:utf-8
import os, sys, time
from multiprocessing import Pool, Queue, Manager

class Out(object):
----def out(self,queue):
--------print("start")
--------while True:
------------item = queue.get()
------------print(item)
------------time.sleep(0.01)


class Data(object):

----def __init__(self):
--------self.pool = Pool(2)
--------self.queue = Manager().Queue()
--------self.out = Out()

----def put(self,item):
--------self.queue.put(item)


----def start(self):
--------print(self.queue.qsize())
--------for _ in range(2):
------------self.pool.apply_async(self.out.out,(self.queue,))

if __name__ == '__main__':

----data = Data()
----for i in range(1000):
--------data.put(i)
----data.start()
----data.pool.close()
----data.pool.join()
----time.sleep(5)
wwqgtxx
2017-07-03 18:15:47 +08:00
这样写才可以,根本还是在于你 Data 的这个 self 不能跨进程传递,所以子进程根本就没执行
dbow
2017-07-03 18:16:52 +08:00
@raycool
@wwqgtxx

这个是忘掉处理 apply_async 的结果造成的误解
apply_async -> result -> result.get() 就能看到异常了, 传递的东西得能 pickle 序列化

Traceback (most recent call last):
File "test.py", line 36, in <module>
print result.get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

想要序列化 class instance, 可以看看 pickle 的文档
https://docs.python.org/2/library/pickle.html
-> Pickling and unpickling normal class instances
wwqgtxx
2017-07-03 18:42:50 +08:00
@dbow 不过我依然没有猜错,的的确确是 Pool 不能序列化
raycool
2017-07-03 20:06:25 +08:00
@wwqgtxx
@dbow
多谢楼上两位大佬的回复
明白了,以前真没关注过序列化这个问题。
根据错误信息也在 stackoverflow 上找到了解决办法。
https://stackoverflow.com/questions/25382455/python-notimplementederror-pool-objects-cannot-be-passed-between-processes

再次感谢。
wwqgtxx
2017-07-03 20:13:38 +08:00
@raycool 不过这个问题在 Linux 上并不一定会出现,因为 linux 上可以使用 fork 机制,所以这个地方并不需要通过序列化来传递参数
raycool
2017-07-03 20:33:35 +08:00
@wwqgtxx 嗯,回头用 linux 试一下,这个问题算是搞明白了,感谢。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/372733

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX