1

外部プログラムを操作し、タイムアウト スレッドを開始する python プログラムがあります。タイムアウト スレッドは 10 分間カウントダウンする必要があり、外部プログラムを操作するスクリプトがその時間内に終了しない場合は、外部プログラムを強制終了する必要があります。

私のスレッドは一見問題なく動作しているように見えます。メイン スクリプトとスレッドは問題なく同時に実行されます。しかし、外部プログラムにポップアップウィンドウが表示されると、スクリプトが停止するため、カウントダウンスレッドでさえカウントが停止するため、仕事が完全に失敗します。

問題は、スクリプトが外部プログラムの API でブロック関数を呼び出し、ポップアップ ウィンドウによってブロックされていることだと思います。メイン プログラムがブロックされる理由は理解できますが、カウントダウン スレッドがブロックされる理由はわかりません。したがって、考えられる解決策の 1 つは、カウントダウン用に別のスクリプトを実行することです。

手がかりを求めてあちこち探しましたが、あまり見つかりませんでした。ここに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")
4

2 に答える 2

1

別の Python スレッドをブロックするための関数呼び出しの考えられる説明の 1 つは、CPython がグローバル インタープリター ロック (GIL) を使用し、ブロック API 呼び出しがそれを解放しないことです (注: CPython はブロック I/O 呼び出しで GIL を解放するため、raw_input()例は次のように動作するはずです。は)。

GIL をリリースするためにバグのある API 呼び出しを行うことができない場合は、スレッドの代わりにプロセスを使用できますmultiprocessing.Process( threading.ThreadAPI は同じです)。異なるプロセスは GIL によって制限されません。

于 2013-11-05T15:49:56.467 に答える
1

迅速で汚れたスレッド化のために、私は通常、サブプロセス コマンドに頼っています。それは非常に堅牢で、OS に依存しません。thread や queue モジュールほどきめの細かい制御はできませんが、プログラムへの外部呼び出しに対しては一般的にうまく機能します。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
于 2013-11-05T13:53:00.237 に答える