在Python中,如何让线程在特定时间内进入休眠状态?

Ros*_*ers 36 python

我知道我可以让线程在特定的时间内睡眠:

time.sleep(NUM)
Run Code Online (Sandbox Code Playgroud)

如何让线程睡到凌晨2点?我必须做数学来确定直到凌晨2点的秒数吗?还是有一些图书馆功能?

(是的,我知道Windows中的cron和等效系统,但我想在python中正确地睡觉我的线程而不依赖于外部激励或处理信号.)

Ros*_*ers 39

这是一个半分辨率解决方案,不考虑时钟抖动或时钟调整.请参阅评论以了解如何摆脱它.

import time
import datetime

# if for some reason this script is still running
# after a year, we'll stop after 365 days
for i in xrange(0,365):
    # sleep until 2AM
    t = datetime.datetime.today()
    future = datetime.datetime(t.year,t.month,t.day,2,0)
    if t.hour >= 2:
        future += datetime.timedelta(days=1)
    time.sleep((future-t).seconds)

    # do 2AM stuff
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,值得注意的是,天真地使用*only*the seconds`属性会导致意想不到的结果.它只包含一天划分的"余数",可以这么说,所以如果持续时间超过一天,你需要添加`.days*24*3600`.显然在这种情况下不是问题,而是捕获那些不熟悉datetime对象的奇怪的人. (5认同)
  • 同意.使用`total_seconds()`代替!(它也返回一个浮点数,`time.sleep`将接受) (5认同)
  • 这个解决方案中有一个错误 - 未来可能不存在:)如果我们在一个月的最后一天怎么办? (2认同)
  • @mnowotka,_用海绵鲍勃的声音,“7年后”_ -- `timedelta` 负责滚动日、月和年。 (2认同)

小智 21

import pause
from datetime import datetime

pause.until(datetime(2015, 8, 12, 2))
Run Code Online (Sandbox Code Playgroud)

  • 该软件包已于14天前更新,现在看来可移植(可在py3上使用) (3认同)
  • 你能链接到`pause`库吗?我在文档中找不到它.这是Python 3的新功能吗? (2认同)

小智 11

稍微更通用的解决方案(基于Ross Rogers 的),以防您也想增加分钟数。

import datetime
import time

def sleepUntil(hour, minute):
    t = datetime.datetime.today()
    future = datetime.datetime(t.year, t.month, t.day, hour, minute)
    if t.timestamp() > future.timestamp():
        future += datetime.timedelta(days=1)
    time.sleep((future-t).total_seconds())
Run Code Online (Sandbox Code Playgroud)

请注意,这将大致休眠到给定时间,并有一些超调(根据我自己的实验,在所需的“睡眠直到”时间后,我的超调高达约 400 毫秒)。如果您需要毫秒级的精确睡眠(<10ms~),我会按照Bobby的建议使用暂停模块。


one*_*one 6

另一种方法,使用sleep,以对数方式减少超时。

def wait_until(end_datetime):
    while True:
        diff = (end_datetime - datetime.now()).total_seconds()
        if diff < 0: return       # In case end_datetime was in past to begin with
        time.sleep(diff/2)
        if diff <= 0.1: return
Run Code Online (Sandbox Code Playgroud)

基于@MZA 的回答和@Mads Y 的评论


car*_*arl 5

一种可能的方法是睡觉一个小时。每小时检查一下时间是否在深夜。如果是这样,请继续进行操作。如果不是,请再睡一个小时,然后继续。

如果用户在一天中更改时钟,则此方法将反映该更改。尽管它需要更多的资源,但应该忽略不计。