如何将Python线程代码转换为多进程代码?

4 投票
1 回答
3150 浏览
提问于 2025-04-16 06:33

我需要把一个使用 threading 的程序改成使用 multiprocessing 的程序,原因有很多,比如全局解释器锁(GIL)和内存泄漏。幸运的是,这些线程之间相对独立,只通过 Queue.Queue 来通信。这个功能在 multiprocessing 中也有,所以看起来一切都还不错。在我进入这个复杂的领域之前,我想先得到一些关于可能遇到的问题的建议:

  1. 我怎么确保我的对象可以通过 Queue 传输?我需要提供一些 __setstate__ 吗?
  2. 我能否相信 put 方法会立刻返回(就像在 threadingQueue 中那样)?
  3. 有没有一些通用的提示或建议?
  4. 除了 Python 文档,还有什么值得阅读的材料吗?

1 个回答

5

第一部分的回答:

所有通过 multiprocessing.Queue(或者 Pipe 等其他方式)传递的东西都必须是可以被“序列化”的。这包括一些基本的数据类型,比如 tuple(元组)、list(列表)和 dict(字典)。如果类比较简单,并且是顶层类(也就是没有嵌套在其他类里面),也是可以的。不过,尝试传递 lambda 表达式是行不通的。

第二部分的回答:

一个 put 操作分为两个部分:它需要一个信号量来修改队列,并且可以选择启动一个喂养线程。所以,如果没有其他的 Process 同时尝试往同一个 Queueput 数据(比如说,只有一个 Process 在写入),这个操作应该会很快。对我来说,这个速度在实际使用中已经足够快了。

第三部分的部分回答:

  • 普通的 multiprocessing.queue.Queue 没有 task_done 方法,所以不能直接替代使用。(一个子类提供了这个方法。)
  • 旧版的 processing.queue.Queue 没有 qsize 方法,而新版的 multiprocessing 版本在这个方面不太准确(记得这一点就好)。
  • 因为文件描述符在 fork 时通常会被继承,所以需要注意在正确的进程中关闭它们。

撰写回答