我有一个python程序,它运行一个外部程序并启动一个超时线程。超时线程应该倒计时10分钟,如果操作外部程序的脚本在那段时间内没有完成,它应该终止外部程序。
我的线程似乎在第一眼就能正常工作,我的主脚本和线程同时运行,没有任何问题。但是如果外部程序中出现弹出窗口,它会停止我的脚本,这样即使倒计时线程也会停止计数,因此完全失败了。
我认为问题是该脚本在外部程序的API中调用阻止功能,该功能被弹出窗口阻止。我理解为什么它阻止我的主程序,但不明白为什么它阻止我的倒计时线程。因此,一个可能的解决方案可能是为倒计时运行一个单独的脚本,但我希望尽可能保持干净,并且为此启动脚本似乎非常混乱。
我到处寻找线索,但我找不到多少。这里有对 gevent库的引用: background function in Python ,但这似乎是一项基本任务,我不想为此包含外部库。
我还找到了一个使用Windows多媒体计时器here的解决方案,但我以前从未使用过这个,恐怕代码不会灵活。脚本仅限Windows,但它可以在XP上的所有Windows上运行。
对于Unix我发现signal.alarm似乎完全符合我的要求,但它不适用于Windows。对此有何选择?
有关如何以最简化的方式使用此功能的任何想法?
这是我正在创建的简化线程(在IDLE中运行以重现问题):
import threading
import time
class timeToKill():
def __init__(self, minutesBeforeTimeout):
self.stop = threading.Event()
self.countdownFrom = minutesBeforeTimeout * 60
def startCountdown(self):
self.countdownThread= threading.Thread(target=self.countdown, args=(self.countdownFrom,))
self.countdownThread.start()
def stopCountdown(self):
self.stop.set()
self.countdownThread.join()
def countdown(self,seconds):
for second in range(seconds):
if(self.stop.is_set()):
break
else:
print (second)
time.sleep(1)
timeout = timeToKill(1)
timeout.startCountdown()
raw_input("Blocking call, waiting for input:\n")
答案 0 :(得分:1)
对于快速和脏的线程,我通常使用子进程命令。它非常强大且独立于操作系统。它没有提供与线程和队列模块一样精细的控制,但对于程序的外部调用通常做得很好。注意必须谨慎使用shell = True。
#this can be any command
p1 = subprocess.Popen(["python", "SUBSCRIPTS/TEST.py", "0"], shell=True)
#the thread p1 will run in the background - asynchronously. If you want to kill it after some time, then you need
#here do some other tasks/computations
time.sleep(10)
currentStatus = p1.poll()
if currentStatus is None: #then it is still running
try:
p1.kill() #maybe try os.kill(p1.pid,2) if p1.kill does not work
except:
#do something else if process is done running - maybe do nothing?
pass
答案 1 :(得分:1)
阻止另一个Python线程的函数调用的一个可能的解释是CPython使用全局解释器锁(GIL)并且阻塞API调用不释放它(注意:CPython在阻塞I / O调用时释放GIL因此你的{ {1}}示例应该按原样运行。)
如果您无法进行错误的API调用以释放GIL,那么您可以使用流程而不是线程,例如multiprocessing.Process
而不是raw_input()
(API是相同的)。不同的流程不受GIL的限制。