python hello world重复_在Python 3中安排重复事件

我正在尝试安排重复事件在Python 3中每分钟运行一次。

我见过类sched.scheduler,但我想知道是否还有另一种方法可以做到这一点。 我听说提到我可以使用多个线程,我不介意这样做。

我基本上要求一些JSON,然后解析它; 它的价值随着时间而变化。

要使用sched.scheduler,我必须创建一个循环来请求它安排even运行一小时:

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()

有什么其他方法可以做到这一点?

复制Python 2的所有"计划"问题。所有这些:stackoverflow.com/search?q=%5Bpython%5D+schedule

重复:stackoverflow.com/questions/373335/…

还有关:stackoverflow.com/q/474528/3701431

您可以使用threading.Timer,但这也会调度一次性事件,类似于调度程序对象的.enter方法。

将一次性调度程序转换为周期性调度程序的正常模式(以任何语言)是使每个事件以指定的间隔重新调度自身。例如,使用sched,我不会像你一样使用循环,而是像:

def periodic(scheduler, interval, action, actionargs=()):

scheduler.enter(interval, 1, periodic,

(scheduler, interval, action, actionargs))

action(*actionargs)

并通过电话启动整个"永久定期时间表"

periodic(scheduler, 3600, query_rate_limit)

或者,我可以使用threading.Timer而不是scheduler.enter,但模式非常相似。

如果您需要更精细的变体(例如,在给定时间或某些条件下停止定期重新安排),那么用一些额外的参数来容纳这些变量并不是很难。

好吧,在java中我有timer.scheduleAtFixedRate()和真正的多线程。并且每个人都说在python中我们写的代码更少......嗯哼......只是说......

@ user1685095遗憾的是,任何类似的通用语句都会有例外。

@Wallacoloo是否意味着并不总是例外? :)

@ user1685095不是那么快!尝试编写没有多次导入的代码,扩展TimerTask,提供run方法,并添加一个单独的类来运行计时器以及创建所有这些对象。可能大约15行代码。 (除非你有更清晰的方法去做;我不是Java最棒的。)

根据Alex Martelli的回答,我已经实现了更容易集成的装饰器版本。 stackoverflow.com/a/48758861/482899

我对这个问题的谦虚态度:

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

用法:

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也是如此!

美丽的类,但如果在循环中执行start(),它有一点问题。由于在另一个线程中执行了_run函数,它可能会传递is_running检查。所以最后的self._timer被重新分配,无法停止。查看我的答案以获取正确的版本。

@fdb:我不确定我理解你的观点。如果使用相同的类实例在循环中执行start(),它将不会执行任何操作。如果您创建一个新实例,它将触发一个不同的计时器(允许您有多个同时计时器)。至于多线程,是的,除了每个start()(或__init__()在同一个线程中调用)之外

这是我对"循环"字的错误:我的意思是对start()函数进行快速调用(使用do ...循环实现)。快速应该比_run()函数设置"is_running"标志更快。

你可以使用时间表。它适用于Python 2.7和3.3,并且非常轻量级:

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)

为什么while循环?,它不会像cron作业一样运行吗?

@Jaydev如果代码在主线程中运行,则需要while循环

使用芹菜。

from celery.task import PeriodicTask

from datetime import timedelta

class ProcessClicksTask(PeriodicTask):

run_every = timedelta(minutes=30)

def run(self, **kwargs):

#do something

基于MestreLion答案,它解决了多线程的一个小问题:

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()

哈,我只是将锁放入原件。这确实是必要的。谢谢这是MestreLion的正确版本

您可以使用Advanced Python Scheduler。它甚至有一个类似cron的界面。

这是一个快速而又脏的非阻塞循环Thread:

#!/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")

没有什么特别的,worker创建了一个带有延迟的新线程。可能不是最有效率,但足够简单。如果您需要更复杂的解决方案,northtree的答案将是您的选择。

基于此,我们可以使用Timer进行相同的操作:

#!/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())

你知道如何添加一个检查来检查这个线程是否还活着吗?我尝试使用try除了块并将t.start()放入try中,但它没有启动线程!我只需要运行一个isAlive()来检查它是否存活

@toing_toing坦率地说,我不知道。如果你在Linux环境中,我建议用一个线程或一个锁文件来更新一个全局变量,但这是我的头脑中的一个想法而不是基于"良好实践",只熟悉Linux。还可以选择使用共享内存来执行此类任务。现在,我对多线程编程知之甚少,所以我建议在网站上提问并引用这个答案,以便人们可以看到你想要处理的代码。

根据Alex Martelli的回答,我已经实现了更容易集成的装饰器版本。

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')

这个装饰器解决方案真的很棒,但我有一个稍微改进的建议:将*args和**kwargs添加到预定的函数调用中,如下所示:def decorator(func, *args, **kwargs): def periodic(scheduler, interval, action, actionargs=(), kwargs={}): scheduler.enter(interval, 1, periodic, (scheduler, interval, action, actionargs, kwargs)) action(*actionargs, **kwargs)以及periodic(scheduler, interval, func, args, kwargs)这样可以使用参数调度函数。

@ opt12每个时间表都改变了参数吗?

不,每个时间表的args是相同的,但你可以装饰任何定期安排的功能。无论他们是否采取参数。这些参数对于每次运行都是相同的,但至少它们可以作为初始参数提供。

看我的样本

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'))

你能解释为什么这比其他8个答案更好吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值