Python多进程异步无法终止进程

1 投票
1 回答
2398 浏览
提问于 2025-04-26 12:09

我有一个无限循环在异步运行,但我无法终止它。这里有一个和我的代码类似的版本:

from multiprocessing import Pool
test_pool = Pool(processes=1)
self.button1.clicked.connect(self.starter)
self.button2.clicked.connect(self.stopper)

    def starter(self):
       global test_pool
       test_pool.apply_async(self.automatizer)

    def automatizer(self):
       i = 0
       while i != 0 :
          self.job1()
          # safe stop point
          self.job2()
          # safe stop point
          self.job3()
          # safe stop point

    def job1(self):
       # doing some stuff


    def job2(self):
       # doing some stuff


    def job3(self):
       # doing some stuff


    def stopper(self):
       global test_pool
       test_pool.terminate()

我的问题是,stopper 函数里的 terminate() 不起作用。我试着把 terminate() 放在 job1、job2、job3 函数里,还是不行;又试着把它放在 starter 函数的循环末尾,结果还是不行。我该怎么停止这个异步进程呢?

虽然随时停止这个进程就可以了,但我想知道能不能在我想要的地方停止?我的意思是,如果给进程发一个停止命令(我不太确定这个命令是什么),我希望它能完成到“# 安全停止点”标记的步骤,然后再终止进程。

暂无标签

1 个回答

1

在正常情况下,你真的应该避免使用 terminate()。这个方法只应该在一些特殊情况下使用,比如程序卡住或者没有反应的时候。正常结束一个进程池的方法是先调用 pool.close(),然后再调用 pool.join()

这两个方法需要你在进程池中执行的函数返回结果,而你调用 pool.join() 时,主进程会一直等到这个函数返回后才继续执行。我建议你添加一个 multiprocess.Queue,这样你就可以告诉子进程退出了:

# this import is NOT the same as multiprocessing.Queue - this is here for the 
# queue.Empty exception
import Queue

queue = multiprocessing.Queue() # not the same as a Queue.Queue()

def stopper(self):
   # don't need "global" keyword to call a global object's method
   # it's only necessary if we want to modify a global
   queue.put("Stop") 
   test_pool.close()
   test_pool.join()

def automatizer(self):
    while True: # cleaner infinite loop - yours was never executing
        for func in [self.job1, self.job2, self.job3]: # iterate over methods
            func() # call each one

            # between each function call, check the queue for "poison pill"
            try:
                if queue.get(block=False) == "Stop":
                    return
            except Queue.Empty:
                pass

因为你没有提供更完整的代码示例,所以你需要自己找出在哪里创建 multiprocessing.Queue,以及如何传递数据。此外,Janne Karila 的评论是对的。如果你一次只使用一个进程,应该把代码改成使用单个 Process,而不是进程池。Process 类也使用一个阻塞的 join() 方法来告诉它在返回后结束。安全结束进程的唯一方法是在“已知安全点”实现某种进程间通信,就像我在这里做的那样。管道也可以用。

撰写回答