如何使用多处理模块终止进程?

How to kill a process using the multiprocessing module?

我有一个本质上只是一个无限循环的进程,我还有一个计时器进程。计时器完成后如何终止循环进程?

def action():
  x = 0
  while True:
      if x < 1000000:
          x = x + 1
      else:
          x = 0

def timer(time):
  time.sleep(time)
  exit()    

loop_process = multiprocessing.Process(target=action)
loop_process.start()
timer_process = multiprocessing.Process(target=timer, args=(time,))
timer_process.start()

我希望 python 脚本在定时器结束后结束。

action()else 之后的一个简单的 return 语句可以完美地工作。此外,您的 timer 功能有误。您的参数与内置库时间同名。

def action():
   x = 0
   while True:
      if x < 1000000:
         x = x + 1
      else:
         x = 0
         return # To exit else it will always revolve in infinite loop

def timer(times):
   time.sleep(times)
   exit()    

loop_process = multiprocessing.Process(target=action)
loop_process.start()
timer_process = multiprocessing.Process(target=timer(10))
timer_process.start()

希望这能回答您的问题!!!

您可以通过使用 sharing state between the processes 并创建一个所有并发进程都可以访问的标志值来实现(尽管这可能有点低效)。

这是我的建议:

import multiprocessing as mp
import time

def action(run_flag):
    x = 0
    while run_flag.value:
        if x < 1000000:
            x = x + 1
        else:
            x = 0

    print('action() terminating')


def timer(run_flag, secs):
    time.sleep(secs)
    run_flag.value = False


if __name__ == '__main__':

    run_flag = mp.Value('I', True)

    loop_process = mp.Process(target=action, args=(run_flag,))
    loop_process.start()

    timer_process = mp.Process(target=timer, args=(run_flag, 2.0))
    timer_process.start()

    loop_process.join()
    timer_process.join()

    print('done')

我认为你不需要为一个计时器做第二个过程。

优雅超时

如果您需要在 action 进程退出之前进行清理,您可以使用 Timer 线程并让 while 循环检查它是否仍然存在。这允许您的工作进程优雅地退出,但您将不得不以降低性能为代价 因为重复的方法调用需要一些时间。不过,如果不是紧密循环,则不一定是问题。

from multiprocessing import Process
from datetime import datetime
from threading import Timer


def action(runtime, x=0):
    timer = Timer(runtime, lambda: None)  # just returns None on timeout
    timer.start()
    while timer.is_alive():
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0

if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action, args=(RUNTIME,))
    p.start()
    print(f'{datetime.now()} {p.name} started')
    p.join()
    print(f'{datetime.now()} {p.name} ended')

示例输出:

2019-02-28 19:18:54.731207 Process-1 started
2019-02-28 19:18:55.738308 Process-1 ended

超时终止

如果您不需要 clean 关闭(您没有使用共享队列、使用数据库等),您可以让父进程 terminate() 指定时间后的工作进程。

terminate()

Terminate the process. On Unix this is done using the SIGTERM signal; on Windows TerminateProcess() is used. Note that exit handlers and finally clauses, etc., will not be executed.

Note that descendant processes of the process will not be terminated – they will simply become orphaned.

Warning If this method is used when the associated process is using a pipe or queue then the pipe or queue is liable to become corrupted and may become unusable by other process. Similarly, if the process has acquired a lock or semaphore etc. then terminating it is liable to cause other processes to deadlock. docs

如果您在父进程中无事可做,您可以简单地 .join(timeout) 工作进程,然后 .terminate()

from multiprocessing import Process
from datetime import datetime

def action(x=0):
    while True:
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0

if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action)
    p.start()
    print(f'{datetime.now()} {p.name} started')
    p.join(RUNTIME)
    p.terminate()
    print(f'{datetime.now()} {p.name} terminated')

示例输出:

2019-02-28 19:22:43.705596 Process-1 started
2019-02-28 19:22:44.709255 Process-1 terminated

如果您想使用 terminate(),但需要您的父级畅通无阻,您也可以为此在父级中使用 Timer-thread。

from multiprocessing import Process
from datetime import datetime
from threading import Timer

def action(x=0):
    while True:
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0


def timeout(process, timeout):
    timer = Timer(timeout, process.terminate)
    timer.start()


if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action)
    p.start()
    print(f'{datetime.now()} {p.name} started')
    timeout(p, RUNTIME)
    p.join()
    print(f'{datetime.now()} {p.name} terminated')

示例输出:

2019-02-28 19:23:45.776951 Process-1 started
2019-02-28 19:23:46.778840 Process-1 terminated