web-dev-qa-db-ja.com

Pythonで60秒ごとに非同期で関数を実行する方法は?

Pythonで60秒ごとに関数を実行したいが、その間ブロックされたくない。

非同期に行うにはどうすればよいですか?

import threading
import time

def f():
    print("hello world")
    threading.Timer(3, f).start()

if __== '__main__':
    f()    
    time.sleep(20)

このコードでは、関数fは20秒のtime.time内で3秒ごとに実行されます。最後にエラーが発生し、threading.timerがキャンセルされていないためだと思います。

キャンセルするにはどうすればよいですか?

前もって感謝します!

57
aF.

Threading.Timerクラスを試すことができます: http://docs.python.org/library/threading.html#timer-objects

import threading

def f(f_stop):
    # do something here ...
    if not f_stop.is_set():
        # call f() again in 60 seconds
        threading.Timer(60, f, [f_stop]).start()

f_stop = threading.Event()
# start calling f now and every 60 sec thereafter
f(f_stop)

# stop the thread when needed
#f_stop.set()
100
David Underhill

最も簡単な方法は、60秒ごとに何かを実行するバックグラウンドスレッドを作成することです。簡単な実装は次のとおりです。

class BackgroundTimer(Thread):   
   def run(self):
      while 1:
        Time.sleep(60)
        # do something


# ... SNIP ...
# Inside your main thread
# ... SNIP ...

timer = BackgroundTimer()
timer.start()

明らかに、「何かをする」に時間がかかる場合は、スリープステートメントでそれに対応する必要があります。しかし、これは適切な近似として機能します。

2
0xfe

それは、その間に実際に何をしたいかによって異なります。スレッドは、それを行うための最も一般的で最も好ましくない方法です。使用する場合、スレッドの問題に注意する必要があります。すべての(Python以外の)コードが複数のスレッドから同時にアクセスできるわけではありません。スレッド間の通信は、Queue.Queue、スレッドを外部から中断することはできません。スレッドの実行中にプログラムを終了すると、インタープリターがハングしたり、誤ったトレースバックが発生したりする可能性があります。

多くの場合、もっと簡単な方法があります。 GUIプログラムでこれを行う場合は、GUIライブラリのタイマーまたはイベント機能を使用してください。すべてのGUIにこれがあります。同様に、Twistedや別のサーバープロセスモデルなどの別のイベントシステムを使用している場合は、メインイベントループにフックして、定期的に関数を呼び出すようにする必要があります。非スレッド化アプローチでは、関数が保留中にプログラムがブロックされますが、関数呼び出し間ではブロックされません。

2
Thomas Wouters

私はグーグルで探して、Python circuits Frameworkを見つけました。
特定のイベント用。

回路の.callEvent(self, event, *channels)メソッドには、発火および応答までのサスペンド機能が含まれています。

指定されたイベントを指定されたチャネルに送信し、ディスパッチされるまで実行を一時停止します。このメソッドは、ハンドラーの最上位実行レベルのyieldの引数としてのみ呼び出すことができます(例: "yield self.callEvent(event)")。イベントがディスパッチされるまでメインループによって呼び出されるジェネレーターを効果的に作成して返します(:func:circuits.core.handlers.handler)。

私と同じようにあなたがそれが有用であることを願っています:)
./ regards

2
synner

スレッドを繰り返し実行する正しい方法は次のとおりだと思います。

import threading
import time

def f():
    print("hello world")  # your code here
    myThread.run()

if __== '__main__':
    myThread = threading.Timer(3, f)  # timer is set to 3 seconds
    myThread.start()
    time.sleep(10)  # it can be loop or other time consuming code here
    if myThread.is_alive():
        myThread.cancel()

このコードでは、関数fは10秒のtime.sleep(10)内で3秒ごとに実行されます。最後に、スレッドの実行がキャンセルされます。

1
syviad

「オンザクロック」メソッド(たとえば、毎時毎時)を呼び出したい場合は、選択したスレッド化メカニズムに次のアイデアを統合できます。

import time

def wait(n):
    '''Wait until the next increment of n seconds'''
    x = time.time()
    time.sleep(n-(x%n))
    print time.asctime()
1
user1054050

単純なスリープループを配置する専用のスレッドを作成しないのはなぜですか。

#!/usr/bin/env python
import time
while True:
   # Your code here
   time.sleep(60)
0
Aif