我的python代码是这样的:
def a():
...
...
subprocess.call()
...
...
def b():
...
...
等等。
我的任务:
1)如果subprocess.call()
在3秒内返回,我的执行应该在subprocess.call()
返回的那一刻继续执行
2)如果subprocess.call()
在3秒内没有返回,subprocess.call()
应该终止,我的执行应该在3秒后继续。
3)在subprocess.call()
返回或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程序包含无限循环时,则应在3秒后终止subprocess.call()并继续执行程序。我应该能够知道subprocess.call()是否被强制终止或成功执行,以便我可以在下面的代码中打印消息。
后端gcc是linux。
答案 0 :(得分:1)
我的任务:
1)如果subprocess.call()在3秒内返回,我的 执行应该在subprocess.call()返回的那一刻继续 2)如果 subprocess.call()在3秒内没有返回 应该终止subprocess.call()并执行 3秒后继续 3)直到subprocess.call()返回或3 秒完成后,不应再进行执行。
在* 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()
答案 1 :(得分:1)
最后,以下代码有效:
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()
答案 2 :(得分:0)
如果您愿意将呼叫转换为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秒。您可以将上述内容转换为类似循环的内容,如果您想要不同的行为,则会不断轮询子进程 - 您只需要跟踪已经过了多长时间。
答案 3 :(得分:-1)
#!/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
我写了上面的代码,它正在工作并满足我所有的约束。 链接https://docs.python.org/2/library/thread.html说:
thread.exit() 提高SystemExit异常。如果没有捕获,这将导致线程以静默方式退出。
所以我认为不应该存在孤儿进程,资源被阻塞等问题。请建议。