【发布时间】:2013-11-16 01:50:58
【问题描述】:
我有一个 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")
【问题讨论】:
-
请给我们一些(希望是)小而完整的代码示例来显示问题,帮助我们重现问题。
-
你究竟是如何“操作”外部程序的(调用阻塞函数)?
-
我在我的示例中添加了一个示例阻塞调用。这个问题现在可以重现了。我希望我的计时器线程在等待输入时继续计数。
-
我注意到,raw_input 仅在 IDE 中阻塞,如果您正常运行它则不会阻塞。因此,为了示例,请在 IDLE 中运行它。
-
这不是一个相当的错误,但在您的代码中,您使用
self.countdown在不同时间表示两种不同的事物。在startCountdown运行之前,它是一个方法,之后它是一个线程实例。您可能应该为其中一种用途选择不同的名称。但它不会改变任何事情,因为您只使用该方法作为线程的目标,并且此时它仍然可用。
标签: python multithreading timeout blocking