418

Pythonで関数を60秒ごとに永久に繰り返し実行したい(Objective CのNSTimerやJSのsetTimeoutのように)。このコードはデーモンとして実行され、cronを使用して毎分Pythonスクリプトを呼び出すのと実質的に似ていますが、ユーザーが設定する必要はありません。

Pythonに実装されたcronに関するこの質問では、ソリューションは事実上x秒間sleep()を実行しているように見えます。私はそのような高度な機能を必要としないので、おそらくこのようなものが機能するでしょう

while True:
    # Code executed here
    time.sleep(60)

このコードに予測可能な問題はありますか?

4

21 に答える 21

337

プログラムにまだイベントループがない場合は、汎用イベントスケジューラを実装するschedモジュールを使用します。

import sched, time
s = sched.scheduler(time.time, time.sleep)
def do_something(sc): 
    print("Doing stuff...")
    # do your stuff
    s.enter(60, 1, do_something, (sc,))

s.enter(60, 1, do_something, (s,))
s.run()

asyncio、、、、、、などのイベントループライブラリをすでに使用している場合は、trio代わりtkinterに既存のイベントループライブラリのメソッドを使用してタスクをスケジュールします。PyQt5gobjectkivy

于 2009-01-23T21:09:33.110 に答える
78

Reactor Patternを実装する Python ネットワーキング ライブラリであるTwistedを検討することをお勧めします。

from twisted.internet import task, reactor

timeout = 60.0 # Sixty seconds

def doWork():
    #do work here
    pass

l = task.LoopingCall(doWork)
l.start(timeout) # call every sixty seconds

reactor.run()

「while True: sleep(60)」はおそらく機能しますが、Twisted はおそらく、最終的に必要になる多くの機能 (デーモン化、ロギング、または bobince によって指摘された例外処理) を既に実装しており、おそらくより堅牢なソリューションになるでしょう。

于 2009-01-23T21:14:06.393 に答える
43

これは、MestreLion のコードを更新したもので、時間の経過とともに漂流するのを回避します。

ここで RepeatedTimer クラスは、OP によって要求された "interval" 秒ごとに指定された関数を呼び出します。スケジュールは、関数の実行にかかる時間に依存しません。外部ライブラリの依存関係がないため、このソリューションが気に入っています。これは純粋な python です。

import threading 
import time

class RepeatedTimer(object):
  def __init__(self, interval, function, *args, **kwargs):
    self._timer = None
    self.interval = interval
    self.function = function
    self.args = args
    self.kwargs = kwargs
    self.is_running = False
    self.next_call = time.time()
    self.start()

  def _run(self):
    self.is_running = False
    self.start()
    self.function(*self.args, **self.kwargs)

  def start(self):
    if not self.is_running:
      self.next_call += self.interval
      self._timer = threading.Timer(self.next_call - time.time(), self._run)
      self._timer.start()
      self.is_running = True

  def stop(self):
    self._timer.cancel()
    self.is_running = False

使用例 (MestreLion の回答からコピー):

from time import sleep

def hello(name):
    print "Hello %s!" % name

print "starting..."
rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start()
try:
    sleep(5) # your long-running job goes here...
finally:
    rt.stop() # better in a try/finally block to make sure the program ends!
于 2016-12-05T00:22:40.053 に答える
32

私が信じるより簡単な方法は次のとおりです。

import time

def executeSomething():
    #code here
    time.sleep(60)

while True:
    executeSomething()

このようにしてコードが実行され、60 秒待機してから再度実行され、待機し、実行されます。複雑にする必要はありません :D

于 2012-11-04T10:26:10.230 に答える
6

それとcronの主な違いは、例外によってデーモンが完全に強制終了されることです。例外キャッチャーとロガーでラップすることをお勧めします。

于 2009-01-23T21:12:17.130 に答える
5

単に使用する

import time

while True:
    print("this will run after every 30 sec")
    #Your code here
    time.sleep(30)
于 2021-05-11T09:45:01.860 に答える
2

私は Tkinter after() メソッドを使用します。これは「ゲームを盗む」ことはありません (以前に提示されたschedモジュールのように)。つまり、他のものを並行して実行できます。

import Tkinter

def do_something1():
  global n1
  n1 += 1
  if n1 == 6: # (Optional condition)
    print "* do_something1() is done *"; return
  # Do your stuff here
  # ...
  print "do_something1() "+str(n1)
  tk.after(1000, do_something1)

def do_something2(): 
  global n2
  n2 += 1
  if n2 == 6: # (Optional condition)
    print "* do_something2() is done *"; return
  # Do your stuff here
  # ...
  print "do_something2() "+str(n2)
  tk.after(500, do_something2)

tk = Tkinter.Tk(); 
n1 = 0; n2 = 0
do_something1()
do_something2()
tk.mainloop()

do_something1()do_something2()並行して実行でき、任意の間隔速度で実行できます。ここでは、2 番目の関数が 2 倍の速さで実行されます。また、いずれかの関数を終了する条件として単純なカウンターを使用したことにも注意してください。プログラムが終了するまで実行する関数 (時計など) がある場合は、他の条件を使用することも、何も使用しないこともできます。

于 2018-03-14T08:27:20.970 に答える