Schedule a repeating event in Python 3
我正在尝试安排重复事件在Python 3中每分钟运行一次。
我见过类
我基本上要求一些JSON,然后解析它; 它的价值随着时间而变化。
要使用
1 2 3 4 5 6 7 | scheduler = sched.scheduler(time.time, time.sleep) # Schedule the event. THIS IS UGLY! for i in range(60): scheduler.enter(3600 * i, 1, query_rate_limit, ()) scheduler.run() |
有什么其他方法可以做到这一点?
您可以使用
将一次性调度程序转换为周期性调度程序的正常模式(以任何语言)是使每个事件以指定的间隔重新调度自身。例如,使用
1 2 3 4 | def periodic(scheduler, interval, action, actionargs=()): scheduler.enter(interval, 1, periodic, (scheduler, interval, action, actionargs)) action(*actionargs) |
并通过电话启动整个"永久定期时间表"
1 | periodic(scheduler, 3600, query_rate_limit) |
或者,我可以使用
如果您需要更精细的变体(例如,在给定时间或某些条件下停止定期重新安排),那么用一些额外的参数来容纳这些变量并不是很难。
我对这个问题的谦虚态度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from threading import Timer class RepeatedTimer(object): def __init__(self, interval, function, *args, **kwargs): self._timer = None self.function = function self.interval = interval 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 |
用法:
1 2 3 4 5 6 7 8 9 10 11 | 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! |
特征:
- 仅限标准库,无外部依赖项
- 使用Alex Martnelli建议的模式
-
即使定时器已经启动/停止,
start() 和stop() 也可以安全地多次调用 - 要调用的函数可以有位置和命名参数
-
您可以随时更改
interval ,它将在下次运行后生效。对于args ,kwargs 甚至function 也是如此!
你可以使用时间表。它适用于Python 2.7和3.3,并且非常轻量级:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import schedule import time def job(): print("I'm working...") schedule.every(10).minutes.do(job) schedule.every().hour.do(job) schedule.every().day.at("10:30").do(job) while 1: schedule.run_pending() time.sleep(1) |
使用芹菜。
1 2 3 4 5 6 7 8 9 | from celery.task import PeriodicTask from datetime import timedelta class ProcessClicksTask(PeriodicTask): run_every = timedelta(minutes=30) def run(self, **kwargs): #do something |
基于MestreLion答案,它解决了多线程的一个小问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | from threading import Timer, Lock class Periodic(object): """ A periodic task running in threading.Timers """ def __init__(self, interval, function, *args, **kwargs): self._lock = Lock() self._timer = None self.function = function self.interval = interval self.args = args self.kwargs = kwargs self._stopped = True if kwargs.pop('autostart', True): self.start() def start(self, from_run=False): self._lock.acquire() if from_run or self._stopped: self._stopped = False self._timer = Timer(self.interval, self._run) self._timer.start() self._lock.release() def _run(self): self.start(from_run=True) self.function(*self.args, **self.kwargs) def stop(self): self._lock.acquire() self._stopped = True self._timer.cancel() self._lock.release() |
您可以使用Advanced Python Scheduler。它甚至有一个类似cron的界面。
这是一个快速而又脏的非阻塞循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/env python3 import threading,time def worker(): print(time.time()) time.sleep(5) t = threading.Thread(target=worker) t.start() threads = [] t = threading.Thread(target=worker) threads.append(t) t.start() time.sleep(7) print("Hello World") |
没有什么特别的,
基于此,我们可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/env python3 import threading,time def hello(): t = threading.Timer(10.0, hello) t.start() print("hello, world",time.time() ) t = threading.Timer(10.0, hello) t.start() time.sleep(12) print("Oh,hai",time.time()) time.sleep(4) print("How's it going?",time.time()) |
根据Alex Martelli的回答,我已经实现了更容易集成的装饰器版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import sched import time import datetime from functools import wraps from threading import Thread def async(func): @wraps(func) def async_func(*args, **kwargs): func_hl = Thread(target=func, args=args, kwargs=kwargs) func_hl.start() return func_hl return async_func def schedule(interval): def decorator(func): def periodic(scheduler, interval, action, actionargs=()): scheduler.enter(interval, 1, periodic, (scheduler, interval, action, actionargs)) action(*actionargs) @wraps(func) def wrap(*args, **kwargs): scheduler = sched.scheduler(time.time, time.sleep) periodic(scheduler, interval, func) scheduler.run() return wrap return decorator @async @schedule(1) def periodic_event(): print(datetime.datetime.now()) if __name__ == '__main__': print('start') periodic_event() print('end') |
看我的样本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import sched, time def myTask(m,n): print n+' '+m def periodic_queue(interval,func,args=(),priority=1): s = sched.scheduler(time.time, time.sleep) periodic_task(s,interval,func,args,priority) s.run() def periodic_task(scheduler,interval,func,args,priority): func(*args) scheduler.enter(interval,priority,periodic_task, (scheduler,interval,func,args,priority)) periodic_queue(1,myTask,('world','hello')) |