【问题标题】:Python scripts that runs every minute without stoping每分钟运行一次且不停歇的 Python 脚本
【发布时间】:2017-08-16 04:22:49
【问题描述】:

我有一个 Python 脚本,它每 1 分钟向我的 API 发送一个发布请求:

while True:
    data = requests.post("URL_HERE", json={
        "api_key":"XXXX",
        "concat": 1,
        "messages": "HI"
    })
    time.sleep(60)

一切正常,但每 2 小时(或多或少)有 2 条同一分钟的记录。示例:

2017-03-22 11:34:46.977255
2017-03-22 11:37:47.231694
2017-03-22 11:37:47.231694
2017-03-22 11:39:48.849003
2017-03-22 11:40:48.907895
...
2017-03-23 13:59:59.150108
2017-03-23 14:00:00.120431
2017-03-23 14:00:00.942033

我猜这是因为“while”中的代码需要几毫秒才能执行,因此,每2-3小时一次,每分钟会有两条记录。

有人知道我该如何解决这个问题吗?我不能使用 cronjobs。

也许是一个异步任务?

如果我希望这个程序永远执行,使用“while”是好的,或者我应该创建一个类似的守护进程?

【问题讨论】:

  • 为这类任务检查 celery

标签: python django daemon


【解决方案1】:

您可以等待当前分钟的剩余秒数,而不是等待 60 秒:

time.sleep(60 - datetime.datetime.now().second)

如果您的工作迟到datetime.datetime.now().second 将是12,您将等待5958 秒。

【讨论】:

  • 你是对的!这应该有效。你认为用“while”而不是守护进程来做这件事可以吗?
  • 后台进程,每隔一段时间等待和做某事是一个守护进程。根据您希望作业的可靠性,您可以查看 cronjobs 或作业队列。从无法使用 cron 来看,我假设您的环境非常有限,作业队列可能不可行。但这完全是一个不同的问题:-)
【解决方案2】:

看看this post。使用时间表可能会奏效。在您的代码上使用该答案将看起来像这样。

import sched, time, requests
schedul = sched.scheduler(time.time, time.sleep)

def send_post():
    data = requests.post("URL_HERE", json={
        "api_key": "XXXX",
        "concat": 1,
        "messages": "HI"
    })

schedul.enter(60, 1, send_post(), (schedul,))
schedul.run()  

【讨论】:

  • 我认为您在send_post() 中缺少另一个schedul.enter(...)
  • 忘了提一下,如果您需要一遍又一遍地运行它,您可以在第一次运行结束时安排新的运行。 (正如尼尔斯指出的)
  • 我认为您还需要send_post(不调用函数)和调度程序参数)
  • @Joakim 我喜欢这种方法,但 Nils Werner 似乎更简单。使用调度器有什么好处?
  • 这取决于您的需求。 Nils 解决方案既紧凑又好,如果它适合您的需求,那就去吧。您可以将 schedular 视为 Python 自己的 cron 作业。如果您想了解更多信息,请查看文档link
【解决方案3】:

如果您跟踪时间,您可以确保不会重复或出现时间漂移。

这是一个例子

interval = 60
next = time.time() + interval

while True:
    if time.time() >= next :
        data = requests.post("URL_HERE", json={
            "api_key":"XXXX",
            "concat": 1,
            "messages": "HI"
        })
        next = next + interval
    time.sleep(next - time.time())

【讨论】:

  • 如果time.sleep returns early,您的解决方案可能会跳过一个周期。一个解决方案是完全删除if
  • 我不明白这是怎么可能的,因为睡眠周期使用时间差而不是绝对时间。能举个具体的例子吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-04
  • 2018-11-10
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 2023-02-19
  • 2011-06-17
相关资源
最近更新 更多