如何将Python线程代码转换为多进程代码?
我需要把一个使用 threading
的程序改成使用 multiprocessing
的程序,原因有很多,比如全局解释器锁(GIL)和内存泄漏。幸运的是,这些线程之间相对独立,只通过 Queue.Queue
来通信。这个功能在 multiprocessing
中也有,所以看起来一切都还不错。在我进入这个复杂的领域之前,我想先得到一些关于可能遇到的问题的建议:
- 我怎么确保我的对象可以通过
Queue
传输?我需要提供一些__setstate__
吗? - 我能否相信
put
方法会立刻返回(就像在threading
的Queue
中那样)? - 有没有一些通用的提示或建议?
- 除了 Python 文档,还有什么值得阅读的材料吗?
1 个回答
5
第一部分的回答:
所有通过 multiprocessing.Queue
(或者 Pipe
等其他方式)传递的东西都必须是可以被“序列化”的。这包括一些基本的数据类型,比如 tuple
(元组)、list
(列表)和 dict
(字典)。如果类比较简单,并且是顶层类(也就是没有嵌套在其他类里面),也是可以的。不过,尝试传递 lambda
表达式是行不通的。
第二部分的回答:
一个 put
操作分为两个部分:它需要一个信号量来修改队列,并且可以选择启动一个喂养线程。所以,如果没有其他的 Process
同时尝试往同一个 Queue
里 put
数据(比如说,只有一个 Process
在写入),这个操作应该会很快。对我来说,这个速度在实际使用中已经足够快了。
第三部分的部分回答:
- 普通的
multiprocessing.queue.Queue
没有task_done
方法,所以不能直接替代使用。(一个子类提供了这个方法。) - 旧版的
processing.queue.Queue
没有qsize
方法,而新版的multiprocessing
版本在这个方面不太准确(记得这一点就好)。 - 因为文件描述符在
fork
时通常会被继承,所以需要注意在正确的进程中关闭它们。