首页 > 解决方案 > 如何使用多处理在python中创建线程?

问题描述

我试图使用 Process 在 python 中创建线程。

但它一直显示错误。

这是我的代码:

from multiprocessing import Process
import threading

class OneProcess(Process):
    def __init__(self):
        super().__init__()
        self.workers = []
        for i in range(5):
            worker = OneThread()
            self.workers.append(worker)

    def run(self):
        for worker in self.workers:
            worker.start()
        for worker in self.workers:
            worker.join()


class OneThread(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        print("do somethings")

class Shell():
    def __init__(self):
        self.first_process = OneProcess()

    def start(self):
        self.first_process.start()


if __name__ == "__main__":
    shell = Shell()
    shell.start()

这是错误:

    ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle _thread.lock objects

我猜它只是不能序列化线程对象?那么有没有什么方法可以实现呢?或者使用 Process 创建线程在 python 中是不可用的?

标签: pythonmultithreading

解决方案


我希望@rdas 将他的评论变成一个实际的答案。由于没有任何消息,我将尽我所能回答:

您的代码实际上可以在 Linux 下运行。所以我猜你是在Windows下运行的(我对其他环境了解不够,比如Mac)。线程是在__init__class 的方法中创建的,该方法OneProcess在与主进程相同的进程下执行。这在下面的修改代码中得到了证明。但是当self.first_process.start()执行导致OneProcess.run()调用的语句时,我们现在正在运行的是子进程,因此必须使用 将OnceProcess对象的内部状态转移到新的子进程pickle,这就是发生错误的地方。通过将线程的创建移到run方法中,没有线程相关的状态要被腌制。

from multiprocessing import Process
import threading
import os

class OneProcess(Process):
    def __init__(self):
        super().__init__()
        print('OneProcess __init__:', os.getpid())


    def run(self):
        print('OneProcess run:', os.getpid())
        self.workers = []
        for i in range(5):
            worker = OneThread()
            self.workers.append(worker)
        for worker in self.workers:
            worker.start()
        for worker in self.workers:
            worker.join()


class OneThread(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        print("do somethings")

class Shell():
    def __init__(self):
        self.first_process = OneProcess()

    def start(self):
        self.first_process.start()


if __name__ == "__main__":
    print('main pid:', os.getpid())
    shell = Shell()
    shell.start()

印刷:

main pid: 25208
OneProcess __init__: 25208
OneProcess run: 18912
do somethings
do somethings
do somethings
do somethings
do somethings

为什么您的原始代码可以在 Linux 中运行?这与 Linux 支持 OSfork()调用有关,它在创建新子进程时复制整个进程,因此不必依赖 usingpickle来传输状态。请参阅当我调用 multiprocessing.Process 时腌制了什么?


推荐阅读