我写了一个函数fun0
,它调用:
p1
,fun1
,fun2
调用另一个进程p2
。p1
和p2
这两个进程都是外部文件。函数fun0
的代码是:
def fun0():
# call the 1. process
p1 = subprocess.Popen(["python", "script1.py"])
try:
p1.wait()
except KeyboardInterrupt:
try:
p1.terminate()
except OSError:
pass
p1.wait()
# call the 1. function
fun1()
# loop 3 times
for i in range(1, 3, 1):
# call the 2. function
fun2()
def fun2():
# call 2. process
p2 = subprocess.Popen(["python", "script2.py"])
try:
p2.wait()
except KeyboardInterrupt:
try:
p2.terminate()
except OSError:
pass
p2.wait()
script_2.py使用线程同时运行两个函数。代码如下:
import threading
def Ref():
read ref. value
return ref. value
def Read():
while read_interval <= some_time:
read value
yield value
def Add():
while delta > error:
while delta > limit :
while True:
value = next(Read())
delta = change delta
check conditions
while True:
value = next(Read())
delta = change delta
check conditions
return result
if __name__ == '__main__':
t0 = threading.Thread(target = Ref)
t0.start()
t0.join()
readTime = datetime.now()
t1 = threading.Thread(target = Read)
t2 = threading.Thread(target = Add)
t1.start()
t2.start()
t1.join()
t2.join()
我想停止执行外部函数fun0()
,即从另一个函数执行。当停止发生时,我还希望函数fun1
,fun2
和进程p1
,p2
停止并可能从它们检索数据。我想知道这将是一种优雅,干净和Pythonic的方式。我正在考虑:
我已经读过这个post 28906558停止使用multiprocessing
的功能应该是这样做的方式,但我想听到更多的意见,谢谢。
出于这个问题的目的,我使用函数fun1
和子进程p1
和p2
的简单倒计时。然后我开始尝试将该功能作为流程解决方案。主程序的代码是:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
#An example of how to terminate the execution of a function
#which calls a process using an external trigger.
import time
import subprocess
from multiprocessing import Process, Queue
def fun0():
# start process1
p1 = subprocess.Popen(["python", "eg_script1_countdown1.py"])
p1_PID = p1.pid
print "p1_PID:", p1_PID
try:
p1.wait()
except KeyboardInterrupt:
try:
p1.terminate()
except OSError:
pass
p1.wait()
# call function1
fun1()
# loop 3 times
for i in range(1, 3, 1):
# call fun2
print "call function 2, loop n.", i
fun2()
def fun1():
for i in range(5,0,-1):
print "fun1 > take five in", i
time.sleep(1)
def fun2():
# start process2
p2 = subprocess.Popen(["python", "eg_script2_countdown2.py"])
p2_PID = p2.pid
print "p2_PID:", p2_PID
try:
p2.wait()
except KeyboardInterrupt:
try:
p2.terminate()
except OSError:
pass
p2.wait()
if __name__ == '__main__':
pMain = Process(target=fun0)
pMain_PID = pMain.pid
print "pMain_PID:", pMain_PID
pMain.start()
time.sleep(20)
pMain.terminate()
第一个被调用文件的代码是:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
#eg_script1_countdown.py
import time
for i in range(10,0,-1):
print "script1.py > have a beer in", i
time.sleep(1)
和第二个文件:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
#eg_script2_countdown.py
import time
for i in range(10,0,-1):
print "script2.py > give love in", i
time.sleep(1)
我正在改变time.sleep(20)
中的__name__ == '__main__'
线,看看内部终止pMain.terminate()
如何影响结果。我发现:
p1
正在运行时触发,它不会终止它,fun1()
正在运行时触发,它会终止该函数,p2
正在运行时触发,它不会终止进程,但会在下一个循环中终止fun2()
。如何在运行时终止子进程p1
和p2
?
我在pMain.daemon = True
之前使用pMain.start()
修改了主程序的代码,如同建议的in this thread但是进程p1
在退出后仍然在背景中运行。
import os
import time
import signal
import subprocess
from subprocess import Popen, PIPE
import multiprocessing
from datetime import datetime
def fun0():
p1 = subprocess.Popen(["python", "eg_script1_countdown1.py"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
#p1 = subprocess.Popen(["python", "eg_script1_countdown1.py"])
global p1_pid
p1_pid = p1.pid
print "p1_pid:", p1_pid
try:
p1.wait()
except KeyboardInterrupt:
try:
p1.terminate()
except OSError:
pass
p1.wait()
# call fun1
fun1()
# loop 3 times
for i in range(3):
# call fun2
print "call fun2, loop n.", i
with open('/home/parovelb/Desktop/Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' for loop n. ' + str(i) + "\n")
fun2()
def fun1():
for i in range(5,0,-1):
print "fun1 > take five in", i
with open('/home/parovelb/Desktop/Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' fun1 ' + str(i) + "\n")
time.sleep(1)
def fun2():
# start process2
p2 = subprocess.Popen(["python", "eg_script2_countdown2.py"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
#p2 = subprocess.Popen(["python", "eg_script2_countdown2.py"])
global p2_pid
p2_pid = p2.pid
try:
p2.wait()
except KeyboardInterrupt:
try:
p2.terminate()
except OSError:
pass
p2.wait()
if __name__ == '__main__':
# original code
pMain = multiprocessing.Process(target=fun0)
pMain.daemon = True
pMain.start()
time.sleep(10)
pMain.terminate()
exit()
根据delegate-sigint-signal...和delegate-signal-handling...帖子中提出的解决方案,我修改了我的主程序的代码:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
"""
This is an example of a simple terminaton of a subprocess with a ctrl+c.
"""
import time
import signal
import subprocess
def signal_handler(signal, frame):
print "outer signal handler"
exit(2)
def fun1():
for i in range(5,0,-1):
print "fun1 > take five in", i
time.sleep(1)
def execute():
# call the process first
proc = subprocess.Popen("python eg_test.py",shell=True)
try:
proc.wait()
except KeyboardInterrupt:
try:
proc.terminate()
except OSError:
pass
# call the function second
fun1()
def main():
signal.signal(signal.SIGINT, signal_handler)
execute()
time.sleep(5)
proc.send_signal(signal.SIGINT)
main()
我还修改了一个仅用于测试运行的外部脚本:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
"""
This is an example of a simple for loop countdown run a subprocess and
terminated with ctrl+c.
"""
import time
import signal
from datetime import datetime
def signal_handler(signal, frame):
print "exiting: inner function"
exit(2)
def main():
#define the signal handler
signal.signal(signal.SIGINT, signal_handler)
# simple for loop countdown
for i in range(20,0,-1):
print "test.py > countdown", i
time.sleep(1)
main()
在中间进程中按下ctrl + c
(外部脚本正在运行)时,它会终止它,然后继续执行fun1()
。问题仍然存在:如何从另一个函数终止execute()
函数?
经过一些试验和错误后,我得到了代码。我觉得还有很多需要改进的地方。主脚本的代码:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
"""
This is an example of a simple terminaton of a subprocess with a ctrl+c.
"""
import os
import time
import signal
import subprocess
import multiprocessing
from datetime import datetime
p1_pid = 0
proc_pid = 0
def signal_handler(signal, frame):
print " main signal handler "
# write to log
with open('.../Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' exiting: main function ' + "\n")
exit(2)
def f1():
for i in range(5,0,-1):
print "f1 > main function", i
# write to log
with open('/home/parovelb/Desktop/Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' main function ' + str(i) + "\n")
time.sleep(1)
def execute():
# call the function second
f1()
# call the process first
global p1, p1_pid
p1 = subprocess.Popen(["python", "eg_test.py"], shell=False)
p1_pid = p1.pid
print "p1_pid", p1_pid
try:
p1.wait()
except KeyboardInterrupt:
try:
p1.terminate()
except OSError:
pass
def kill_them_all():
time.sleep(10)
print "p1_pid", p1_pid
os.kill(p1_pid,signal.SIGINT)
os.kill(proc_pid,signal.SIGINT)
def main():
# define signal handler
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
global proc, proc_pid
proc = multiprocessing.Process(target=execute)
proc_pid = proc.pid
print "proc_pid", proc_pid
proc_end = multiprocessing.Process(target=kill_them_all)
proc.start()
proc_end.start()
proc.join()
proc_end.join()
main()
外部脚本的代码:
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-
import time
import signal
from datetime import datetime
def signal_handler(signal, frame):
print " external signal handler "
with open('.../Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' exiting: external function ' + "\n")
exit(2)
def main():
#define the signal handler
signal.signal(signal.SIGINT, signal_handler)
# simple for loop countdown
for i in range(20,0,-1):
print "eg_test.py > external file > main function", i
with open('.../Python2.7/log.txt', 'a') as log:
log.write(str(datetime.now()) + ' external function ' + str(i) + "\n")
time.sleep(1)
main()