Python多处理子进程自终止和pickle

2024-06-28 19:04:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习多处理模块和装饰器。关于下面的代码,我有两个问题:

from time import sleep
from multiprocessing import Process

class async:
    def __init__(self, function):
        self.func = function
    def __call__(self, *args, **kwargs):
        p = Process(target = self.func, args = args, kwargs = kwargs)
        p.start()

@async
def printA():
    sleep(1)
    print("A")

def main():
    printA()
    printA()
    printA()

    #do more work

if __name__ == "__main__":
    main()
  1. 现在我得到了PicklingError: Can't pickle <function printA at 0x00000273F97FF1E0>: it's not the same object as __main__.printA
    我不知道怎么解决这个问题。我觉得这是在我工作的unix机器上运行的,是Windows的东西吗?

  2. 我希望子进程在完成时自动终止。我尝试在结尾用sys.exit()包装函数,并将其作为进程的目标,但是sys.exit()似乎无法正确终止僵尸进程。正确的方法是什么?

我不想阻塞join(),也不想设置daemon=True。最终目标是有人可以导入这个模块,将@async放在任何函数上,它将在一个单独的进程中运行,然后在到达函数末尾时自行终止。在


Tags: 模块函数fromimportselfasync进程main
1条回答
网友
1楼 · 发布于 2024-06-28 19:04:50
  1. 酸洗错误:我可以重现该问题。在Linux上它工作得很好,在Windows上就不行了。问题似乎出在Windows上不能正确地处理装饰器。删除decorator会导致这段工作代码(当然这不是您想要的,但可能会说服您尝试另一种设计方法)。还有一个this thread on SO也有完全相同的问题。在

    from time import sleep
    from multiprocessing import Process
    
    def printA():
        sleep(1)
        print("A")
    
    def main():
        for i in range(3):
            p = Process(target = printA)
            p.start()
    
        #do more work
    
    if __name__ == "__main__":
        main()
    
  2. 僵尸进程:为了避免僵尸进程,您需要让父进程读取其子进程的退出代码,您需要在父进程中对子进程运行join()来完成此操作。你可以像这样在装饰店里这样做:

    class async:
        def __init__(self, function):
            self.func = function
            self.pool = []
        def __call__(self, *args, **kwargs):
            p = Process(target = self.func, args = args, kwargs = kwargs)
            self.pool.append(p)
            p.start()
        def __del__(self):
            for p in self.pool:
                p.join()
    

这使用了python只执行@async的一个实例的效果,因此您可以收集self.pool中的所有进程。注意,这只在主进程的出口运行,因为python不会在前面删除异步实例。在

相关问题 更多 >