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

时间:2019-02-28 15:48:33

标签: python python-3.x multiprocessing python-multiprocessing

我有一个本质上只是无限循环的进程,而我有另一个进程是计时器。计时器完成后,如何杀死循环进程?

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脚本结束。

3 个答案:

答案 0 :(得分:1)

elseaction()之后的简单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()

希望这能回答您的问题!

答案 1 :(得分:1)

您可以通过使用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')

答案 2 :(得分:1)

我认为您不需要为计时器做第二步处理。

优雅超时

如果需要在退出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 (您不使用共享队列,不使用DB等),则可以让父进程terminate()在指定的时间后执行工作进程。

  

terminate()

     

终止该过程。在Unix上,这是使用SIGTERM信号完成的。在Windows上使用TerminateProcess()。请注意,退出处理程序和finally子句等将不会执行。

     

请注意,该进程的后代进程不会终止-它们只会变得孤立。

     
    

警告如果在关联的进程使用管道或队列时使用此方法,则该管道或队列可能会损坏,并可能无法被其他进程使用。同样,如果进程已获取了锁或信号量等,则终止该进程可能会导致其他进程死锁。 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线程。

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