Run certain code every n seconds [duplicate]

2018-12-31 21:34发布

问题:

This question already has an answer here:

  • What is the best way to repeatedly execute a function every x seconds in Python? 15 answers

Is there a way to, for example, print Hello World! every n seconds? For example, the program would go through whatever code I had, then once it had been 5 seconds (with time.sleep()) it would execute that code. I would be using this to update a file though, not print Hello World.

For example:

startrepeat(\"print(\'Hello World\')\", .01) # Repeats print(\'Hello World\') ever .01 seconds

for i in range(5):
    print(i)

>> Hello World!
>> 0
>> 1
>> 2
>> Hello World!
>> 3
>> Hello World!
>> 4

回答1:

import threading

def printit():
  threading.Timer(5.0, printit).start()
  print \"Hello, World!\"

printit()

# continue with the rest of your code


回答2:

My humble take on the subject, a generalization of Alex Martelli\'s answer, with start() and stop() control:

from threading import Timer

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.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._timer = Timer(self.interval, self._run)
            self._timer.start()
            self.is_running = True

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

Usage:

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!

Features:

  • Standard library only, no external dependencies
  • start() and stop() are safe to call multiple times even if the timer has already started/stopped
  • function to be called can have positional and named arguments
  • You can change interval anytime, it will be effective after next run. Same for args, kwargs and even function!


回答3:

Save yourself a schizophrenic episode and use the Advanced Python scheduler: http://pythonhosted.org/APScheduler

The code is so simple:

from apscheduler.scheduler import Scheduler

sched = Scheduler()
sched.start()

def some_job():
    print \"Every 10 seconds\"

sched.add_interval_job(some_job, seconds = 10)

....
sched.shutdown()


回答4:

def update():
    import time
    while True:
        print \'Hello World!\'
        time.sleep(5)

That\'ll run as a function. The while True: makes it run forever. You can always take it out of the function if you need.



回答5:

Here is a simple example compatible with APScheduler 3.00+:

# note that there are many other schedulers available
from apscheduler.schedulers.background import BackgroundScheduler

sched = BackgroundScheduler()

def some_job():
    print(\'Every 10 seconds\')

# seconds can be replaced with minutes, hours, or days
sched.add_job(some_job, \'interval\', seconds=10)
sched.start()

...

sched.shutdown()

Alternatively, you can use the following. Unlike many of the alternatives, this timer will execute the desired code every n seconds exactly (irrespective of the time it takes for the code to execute). So this is a great option if you cannot afford any drift.

import time
from threading import Event, Thread

class RepeatedTimer:

    \"\"\"Repeat `function` every `interval` seconds.\"\"\"

    def __init__(self, interval, function, *args, **kwargs):
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.start = time.time()
        self.event = Event()
        self.thread = Thread(target=self._target)
        self.thread.start()

    def _target(self):
        while not self.event.wait(self._time):
            self.function(*self.args, **self.kwargs)

    @property
    def _time(self):
        return self.interval - ((time.time() - self.start) % self.interval)

    def stop(self):
        self.event.set()
        self.thread.join()


# start timer
timer = RepeatedTimer(10, print, \'Hello world\')

# stop timer
timer.stop()


回答6:

Here\'s a version that doesn\'t create a new thread every n seconds:

from threading import Event, Thread

def call_repeatedly(interval, func, *args):
    stopped = Event()
    def loop():
        while not stopped.wait(interval): # the first call is in `interval` secs
            func(*args)
    Thread(target=loop).start()    
    return stopped.set

The event is used to stop the repetitions:

cancel_future_calls = call_repeatedly(5, print, \"Hello, World\")
# do something else here...
cancel_future_calls() # stop future calls

See Improve current implementation of a setInterval python



回答7:

You can start a separate thread whose sole duty is to count for 5 seconds, update the file, repeat. You wouldn\'t want this separate thread to interfere with your main thread.