Python 2.7中是否有类似于Go的`time.Tick`或Netty的`HashedWheelTimer`的东西?

3

我写了很多依赖于精确周期方法调用的代码。我一直在使用Python的futures库将调用提交到运行时的线程池中,并在循环中在调用之间进行睡眠:

executor = ThreadPoolExecutor(max_workers=cpu_count())

def remote_call():
    # make a synchronous bunch of HTTP requests

def loop():
    while True:
        # do work here
        executor.submit(remote_call)
        time.sleep(60*5)

然而,我注意到这种实现在长时间运行后会引入一些漂移(例如,我已经运行了这段代码约10个小时,发现漂移了约7秒)。对于我的工作,我需要它在准确的秒数上运行,毫秒甚至更好。有些人指向了 asyncio"Fire and forget" python async/await),但我无法在Python 2.7中使其工作。
我不想要任何黑客行为。我真正想要的是类似于Go的 time.Tick 或Netty的 HashedWheelTimer

{btsdaf} - Paulo Scardine
还有一些关于操作系统的图表也很有趣:https://dev59.com/pHNA5IYBdhLWcg3wAItP - Paulo Scardine
不是重复内容。虽然这个回答很明确:https://dev59.com/O2035IYBdhLWcg3wMNCW#34366451 - nmurthy
@nmurthy:我认为那里的信息对于Python 3已经过时了,虽然我不知道Python 2的情况,而且我实际上也没有在Python 2或3上运行过这个实验 - 我只是检查了源代码并发现Python 3正在使用_PyTime_GetMonotonicClock()来获取时间。不幸的是,无论Python 2的time.sleep是否单调,我都不认为Python 2在任何地方公开了一个平台无关的单调时钟。(Python 3有time.monotonic。) - user2357112
1个回答

5

Python 中没有类似的东西。您需要手动调整睡眠时间以考虑工作时间。

您可以将其合并到迭代器中,就像 Go 的 time.Tick 通道一样:

import itertools
import time
import timeit

def tick(interval, initial_wait=False):
    # time.perf_counter would probably be more appropriate on Python 3
    start = timeit.default_timer()

    if not initial_wait:
        # yield immediately instead of sleeping
        yield

    for i in itertools.count(1):
        time.sleep(start + i*interval - timeit.default_timer())
        yield

for _ in tick(300):
    # Will execute every 5 minutes, accounting for time spent in the loop body.
    do_stuff()

请注意,上述计时器在您开始迭代时开始计时,而不是在调用tick时开始计时,这一点很重要,如果您尝试启动一个计时器并将其保存到稍后使用。此外,它不会发送时间,并且如果接收者速度较慢,它不会丢失任何滴答声。如果需要,您可以自行调整所有这些内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接