外部プログラムを操作してタイムアウトスレッドを開始するPythonプログラムがあります。タイムアウトスレッドは10分間カウントダウンする必要があり、外部プログラムを操作するスクリプトがその時間内に終了しない場合は、外部プログラムを強制終了する必要があります。
私のスレッドは一見正常に動作しているように見えます。メインスクリプトとスレッドは問題なく同時に実行されます。しかし、外部プログラムにポップアップウィンドウが表示されると、スクリプトが停止するため、カウントダウンスレッドでさえカウントが停止するため、完全に失敗します。
問題は、スクリプトが外部プログラムのAPIでブロック関数を呼び出し、ポップアップウィンドウによってブロックされていることだと思います。メインプログラムがブロックされる理由は理解できますが、カウントダウンスレッドがブロックされる理由はわかりません。したがって、考えられる解決策の1つは、カウントダウン用に別のスクリプトを実行することですが、できるだけクリーンに保ちたいので、このためのスクリプトを開始するのは非常に面倒なようです。
手がかりをどこでも探しましたが、あまり見つかりませんでした。ここにgeventライブラリへの参照がありました:Pythonのbackground関数ですが、これは非常に基本的なタスクのようで、このための外部ライブラリを含めたくありません。
また、ここでWindowsマルチメディアタイマーを使用するソリューションを見つけましたが、これまでこれを使用したことがなく、コードがこれに柔軟に対応できないのではないかと心配しています。スクリプトは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")
別のPythonスレッドをブロックする関数呼び出しの考えられる説明の1つは、CPythonがグローバルインタープリターロック(GIL)を使用し、ブロッキングAPI呼び出しがそれを解放しないことです(注:CPythonはI / O呼び出しのブロック時にGILを解放するため、raw_input()
例は次のように機能するはずです。です)。
バグのあるAPI呼び出しを行ってGILを解放できない場合は、スレッドの代わりにプロセスを使用できます。たとえば、multiprocessing.Process
代わりにthreading.Thread
(APIは同じです)。さまざまなプロセスがGILによって制限されていません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加