在 n 秒后终止 python 中的函数调用
terminating a function call in python after n seconds
我的 python 代码是这样的:
def a():
...
...
subprocess.call()
...
...
def b():
...
...
等等。
我的任务:
1) 如果 subprocess.call()
returns 在 3 秒内,我的执行应该在 subprocess.call()
returns.
的那一刻继续
2) 如果 subprocess.call()
在 3 秒内没有 return,则 subprocess.call()
应该终止,我的执行应该在 3 秒后继续。
3) 直到 subprocess.call()
returns 或 3 秒结束,不应再执行。
这可以用线程来完成,但是怎么做呢?
真实代码的相关部分是这样的:
...
cmd = ["gcc", "-O2", srcname, "-o", execname];
p = subprocess.Popen(cmd,stderr=errfile)//compiling C program
...
...
inputfile=open(input,'w')
inputfile.write(scanf_elements)
inputfile.close()
inputfile=open(input,'r')
tempfile=open(temp,'w')
subprocess.call(["./"+execname,str(commandline_argument)],stdin=inputfile,stdout=tempfile); //executing C program
tempfile.close()
inputfile.close()
...
...
我正在尝试使用 python 编译和执行 C 程序。
当我使用 subprocess.call() 执行 C 程序时,假设 C 程序包含无限循环,那么 subprocess.call() 应该在 3 秒后终止,程序应该继续。我应该能够知道 subprocess.call() 是被强制终止还是成功执行,以便我可以相应地在以下代码中打印消息。
后端gcc属于linux.
如果您愿意将调用转换为 Popen
构造函数而不是 call
(与 运行 gcc
相同),那么一种方法是方法是等待 3 秒,轮询子进程,然后根据它的 returncode
属性是否仍然是 None
来采取行动。考虑以下高度人为的示例:
import sys
import time
import logging
import subprocess
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
if __name__ == '__main__':
logging.info('Main context started')
procCmd = 'sleep %d' % int(sys.argv[1])
proc = subprocess.Popen(procCmd.split())
time.sleep(3)
if proc.poll() is None:
logging.warning('Child process has not ended yet, terminating now')
proc.terminate()
else:
logging.info('Child process ended normally: return code = %s' % str(proc.returncode))
logging.info('Main context doing other things now')
time.sleep(5)
logging.info('Main context ended')
这会导致不同的日志输出,具体取决于子进程是否在 3 秒内完成:
$ python parent.py 1
2015-01-18 07:00:56,639 INFO Main context started
2015-01-18 07:00:59,645 INFO Child process ended normally: return code = 0
2015-01-18 07:00:59,645 INFO Main context doing other things now
2015-01-18 07:01:04,651 INFO Main context ended
$ python parent.py 10
2015-01-18 07:01:05,951 INFO Main context started
2015-01-18 07:01:08,957 WARNING Child process has not ended yet, terminating now
2015-01-18 07:01:08,957 INFO Main context doing other things now
2015-01-18 07:01:13,962 INFO Main context ended
请注意,即使子进程比这更早完成,上述方法也会始终等待 3 秒。如果您想要不同的行为,您可以将上面的代码转换成一个循环,不断轮询子进程——您只需要跟踪已经过去了多少时间。
#!/usr/bin/python
import thread
import threading
import time
import subprocess
import os
ret=-1
def b(arg):
global ret
ret=subprocess.call(arg,shell=True);
thread.start_new_thread(b,("echo abcd",))
start = time.time()
while (not (ret == 0)) and ((time.time() - start)<=3):
pass
if (not (ret == 0)) :
print "failed"
elapsed = (time.time() - start)
print elapsed
thread.exit()
elif (ret == 0):#ran before 3 sec
print "successful"
elapsed = (time.time() - start)
print elapsed
我已经编写了上面的代码,它可以正常工作并满足我的所有限制。
link https://docs.python.org/2/library/thread.html 表示:
thread.exit()
引发 SystemExit 异常。当没有被捕获时,这将导致线程静默退出。
所以我想应该不会出现孤儿进程、资源阻塞等问题,请指教
My task:
1) If subprocess.call() returns within 3 seconds, my
execution should continue the moment subprocess.call() returns.
2) If
subprocess.call() does not return within 3 seconds, the
subprocess.call() should be terminated and my execution should
continue after 3 seconds.
3) Until subprocess.call() returns or 3
seconds finishes, the further execution should not take place.
在 *nix 上,您可以使用 signal.alarm()
-based solution:
import signal
import subprocess
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# set signal handler
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(3) # produce SIGALRM in 3 seconds
try:
process.wait() # wait for the process to finish
signal.alarm(0) # cancel alarm
except Alarm: # subprocess does not return within 3 seconds
process.terminate() # terminate subprocess
process.wait()
这是一个基于 threading.Timer()
的便携式解决方案:
import subprocess
import threading
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# terminate process in 3 seconds
def terminate():
if process.poll() is None:
try:
process.terminate()
except EnvironmentError:
pass # ignore
timer = threading.Timer(3, terminate)
timer.start()
process.wait()
timer.cancel()
下面的代码终于起作用了:
import subprocess
import threading
import time
def process_tree_kill(process_pid):
subprocess.call(['taskkill', '/F', '/T', '/PID', process_pid])
def main():
cmd = ["gcc", "-O2", "a.c", "-o", "a"];
p = subprocess.Popen(cmd)
p.wait()
print "Compiled"
start = time.time()
process = subprocess.Popen("a",shell=True)
print(str(process.pid))
# terminate process in timeout seconds
timeout = 3 # seconds
timer = threading.Timer(timeout, process_tree_kill,[str(process.pid)])
timer.start()
process.wait()
timer.cancel()
elapsed = (time.time() - start)
print elapsed
if __name__=="__main__":
main()
我的 python 代码是这样的:
def a():
...
...
subprocess.call()
...
...
def b():
...
...
等等。
我的任务:
1) 如果 subprocess.call()
returns 在 3 秒内,我的执行应该在 subprocess.call()
returns.
的那一刻继续
2) 如果 subprocess.call()
在 3 秒内没有 return,则 subprocess.call()
应该终止,我的执行应该在 3 秒后继续。
3) 直到 subprocess.call()
returns 或 3 秒结束,不应再执行。
这可以用线程来完成,但是怎么做呢?
真实代码的相关部分是这样的:
...
cmd = ["gcc", "-O2", srcname, "-o", execname];
p = subprocess.Popen(cmd,stderr=errfile)//compiling C program
...
...
inputfile=open(input,'w')
inputfile.write(scanf_elements)
inputfile.close()
inputfile=open(input,'r')
tempfile=open(temp,'w')
subprocess.call(["./"+execname,str(commandline_argument)],stdin=inputfile,stdout=tempfile); //executing C program
tempfile.close()
inputfile.close()
...
...
我正在尝试使用 python 编译和执行 C 程序。 当我使用 subprocess.call() 执行 C 程序时,假设 C 程序包含无限循环,那么 subprocess.call() 应该在 3 秒后终止,程序应该继续。我应该能够知道 subprocess.call() 是被强制终止还是成功执行,以便我可以相应地在以下代码中打印消息。
后端gcc属于linux.
如果您愿意将调用转换为 Popen
构造函数而不是 call
(与 运行 gcc
相同),那么一种方法是方法是等待 3 秒,轮询子进程,然后根据它的 returncode
属性是否仍然是 None
来采取行动。考虑以下高度人为的示例:
import sys
import time
import logging
import subprocess
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
if __name__ == '__main__':
logging.info('Main context started')
procCmd = 'sleep %d' % int(sys.argv[1])
proc = subprocess.Popen(procCmd.split())
time.sleep(3)
if proc.poll() is None:
logging.warning('Child process has not ended yet, terminating now')
proc.terminate()
else:
logging.info('Child process ended normally: return code = %s' % str(proc.returncode))
logging.info('Main context doing other things now')
time.sleep(5)
logging.info('Main context ended')
这会导致不同的日志输出,具体取决于子进程是否在 3 秒内完成:
$ python parent.py 1
2015-01-18 07:00:56,639 INFO Main context started
2015-01-18 07:00:59,645 INFO Child process ended normally: return code = 0
2015-01-18 07:00:59,645 INFO Main context doing other things now
2015-01-18 07:01:04,651 INFO Main context ended
$ python parent.py 10
2015-01-18 07:01:05,951 INFO Main context started
2015-01-18 07:01:08,957 WARNING Child process has not ended yet, terminating now
2015-01-18 07:01:08,957 INFO Main context doing other things now
2015-01-18 07:01:13,962 INFO Main context ended
请注意,即使子进程比这更早完成,上述方法也会始终等待 3 秒。如果您想要不同的行为,您可以将上面的代码转换成一个循环,不断轮询子进程——您只需要跟踪已经过去了多少时间。
#!/usr/bin/python
import thread
import threading
import time
import subprocess
import os
ret=-1
def b(arg):
global ret
ret=subprocess.call(arg,shell=True);
thread.start_new_thread(b,("echo abcd",))
start = time.time()
while (not (ret == 0)) and ((time.time() - start)<=3):
pass
if (not (ret == 0)) :
print "failed"
elapsed = (time.time() - start)
print elapsed
thread.exit()
elif (ret == 0):#ran before 3 sec
print "successful"
elapsed = (time.time() - start)
print elapsed
我已经编写了上面的代码,它可以正常工作并满足我的所有限制。 link https://docs.python.org/2/library/thread.html 表示:
thread.exit() 引发 SystemExit 异常。当没有被捕获时,这将导致线程静默退出。
所以我想应该不会出现孤儿进程、资源阻塞等问题,请指教
My task:
1) If subprocess.call() returns within 3 seconds, my execution should continue the moment subprocess.call() returns.
2) If subprocess.call() does not return within 3 seconds, the subprocess.call() should be terminated and my execution should continue after 3 seconds.
3) Until subprocess.call() returns or 3 seconds finishes, the further execution should not take place.
在 *nix 上,您可以使用 signal.alarm()
-based solution:
import signal
import subprocess
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# set signal handler
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(3) # produce SIGALRM in 3 seconds
try:
process.wait() # wait for the process to finish
signal.alarm(0) # cancel alarm
except Alarm: # subprocess does not return within 3 seconds
process.terminate() # terminate subprocess
process.wait()
这是一个基于 threading.Timer()
的便携式解决方案:
import subprocess
import threading
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# terminate process in 3 seconds
def terminate():
if process.poll() is None:
try:
process.terminate()
except EnvironmentError:
pass # ignore
timer = threading.Timer(3, terminate)
timer.start()
process.wait()
timer.cancel()
下面的代码终于起作用了:
import subprocess
import threading
import time
def process_tree_kill(process_pid):
subprocess.call(['taskkill', '/F', '/T', '/PID', process_pid])
def main():
cmd = ["gcc", "-O2", "a.c", "-o", "a"];
p = subprocess.Popen(cmd)
p.wait()
print "Compiled"
start = time.time()
process = subprocess.Popen("a",shell=True)
print(str(process.pid))
# terminate process in timeout seconds
timeout = 3 # seconds
timer = threading.Timer(timeout, process_tree_kill,[str(process.pid)])
timer.start()
process.wait()
timer.cancel()
elapsed = (time.time() - start)
print elapsed
if __name__=="__main__":
main()