我有一个本质上只是无限循环的进程,而我有另一个进程是计时器。计时器完成后,如何杀死循环进程?
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脚本结束。
答案 0 :(得分:1)
在else
中action()
之后的简单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