V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
raycool
V2EX  ›  Python

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

  •  
  •   raycool · 2017-07-03 17:41:39 +08:00 · 3295 次点击
    这是一个创建于 2707 天前的主题,其中的信息可能已经有所发展或是发生改变。

    直接上代码:

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

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

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

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

    10 条回复    2017-07-03 20:33:35 +08:00
    raycool
        1
    raycool  
    OP
       2017-07-03 17:46:42 +08:00
    raycool
        2
    raycool  
    OP
       2017-07-03 17:51:27 +08:00
    为嘛主题上面不能显示代码。也不让在回复中连续插入代码。
    wwqgtxx
        3
    wwqgtxx  
       2017-07-03 17:54:39 +08:00 via iPhone
    可能是因为 Pool 不能跨进程传递,你试试
    self.pool.apply_async(Data.out,(self, self.queue))
    wwqgtxx
        4
    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
        5
    wwqgtxx  
       2017-07-03 18:15:47 +08:00
    这样写才可以,根本还是在于你 Data 的这个 self 不能跨进程传递,所以子进程根本就没执行
    dbow
        6
    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
        7
    wwqgtxx  
       2017-07-03 18:42:50 +08:00
    @dbow 不过我依然没有猜错,的的确确是 Pool 不能序列化
    raycool
        8
    raycool  
    OP
       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
        9
    wwqgtxx  
       2017-07-03 20:13:38 +08:00
    @raycool 不过这个问题在 Linux 上并不一定会出现,因为 linux 上可以使用 fork 机制,所以这个地方并不需要通过序列化来传递参数
    raycool
        10
    raycool  
    OP
       2017-07-03 20:33:35 +08:00
    @wwqgtxx 嗯,回头用 linux 试一下,这个问题算是搞明白了,感谢。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2666 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:06 · PVG 20:06 · LAX 04:06 · JFK 07:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.