简体   繁体   English

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

[英]Python Multiprocessing Child Process Self Termination and PickleError

I'm trying to learn the multiprocessing module and decorators. 我正在尝试学习多处理模块和装饰器。 I have two questions about the code below: 我对以下代码有两个疑问:

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. Right now I'm getting PicklingError: Can't pickle <function printA at 0x00000273F97FF1E0>: it's not the same object as __main__.printA 现在我正在获取PicklingError: Can't pickle <function printA at 0x00000273F97FF1E0>: it's not the same object as __main__.printA
    I'm not sure how to fix this. 我不确定如何解决此问题。 I feel like this was working on my work unix machine, is it a Windows thing? 我觉得这是在我的工作unix机器上工作的,这是Windows的事情吗?

  2. I want the child Processes to self terminate upon completion. 我希望子进程在完成时自行终止。 I tried wrapping the function with sys.exit() at the end, and using that as the target for the Process, but sys.exit() doesn't seem to properly terminate the zombie processes. 我尝试在最后用sys.exit()包装该函数,并将其用作Process的目标,但是sys.exit()似乎无法正确终止僵尸进程。 What would be the correct way? 正确的方法是什么?

I don't want to do a blocking join() , nor set daemon=True . 我不想执行阻塞join() ,也不想设置daemon=True The end goal would be someone could import this module, put @async on any function, and it would run in a separate process and then terminate itself when it reaches the end of the function. 最终目标是有人可以导入此模块,将@async放在任何函数上,它将在单独的进程中运行,然后在到达函数末尾时自行终止。

  1. Pickling Error : I could reproduce the issue. 酸洗错误 :我可以重现该问题。 On Linux it works just fine, on Windows it doesn't. 在Linux上,它可以正常工作,而在Windows上,则不能。 The issue seems to be the decorator which cannot be pickled correctly on Windows. 问题似乎是在Windows上无法正确腌制的装饰器。 Removing the decorator results in this working code (of course that's not what you want, but might convince you to try out a different approach of your design). 删除装饰器将产生此工作代码(当然这不是您想要的,但可能会说服您尝试另一种设计方法)。 There's also this thread on SO with the exact same problem. 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. Zombie processes : To avoid zombie processes you need to have the parent read its childrens exit codes, you need to run join() in the parent on the child processes to do that. 僵尸进程 :要避免僵尸进程,您需要让父进程读取其子进程的退出代码,您需要在子进程的父进程中运行join()来执行此操作。 You could do that in the decorator like this: 您可以像这样在装饰器中执行此操作:

     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() 

This uses the effect that python does only one instance of @async , thus you can gather all the processes in self.pool . 这利用了python只执行@async一个实例的@async ,因此您可以将所有进程收集在self.pool Note, that this is only run at the exit of the main process, as python would not drop the async instance earlier. 请注意,此操作仅在主进程的出口运行,因为python不会更早删除异步实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM