Python多进程队列的get方法与sleep的超时比较

-1 投票
1 回答
4993 浏览
提问于 2025-04-18 13:04

我找不到关于Python中队列的get方法带超时的文档:get([block[, timeout]]),而关于Python的time.sleep()却有很好的文档,链接在这里:http://www.pythoncentral.io/pythons-time-sleep-pause-wait-sleep-stop-your-code/

我用Linux的时间工具测试了一个循环,分别是5、500和5000,时间间隔都是100毫秒,结果看起来差不多。

代码片段1:使用队列超时

while True:
    try:
        if self._queue.get(True,period) == '!STOP!: break
    except:
        # Queue.Empty session, keep going
        -- do stuff here --

代码片段2:使用时间睡眠

while True:
    try:
        if self._queue.get_nowait() == '!STOP!: break
    except:
        # Queue.Empty session, keep going
        -- do stuff here --
        time.sleep(period)

我更喜欢代码片段1,因为它不是先“睡觉”,然后再检查队列,而是“睡觉”的同时检查队列。当然,这个问题其实不太重要,因为时间间隔通常在0.100到0.500秒之间,但我想确认在queue.get中没有遗漏什么。

1 个回答

1

正如你所说,第一种选择更好,因为它不是无条件地睡眠一段时间(period),然后检查队列里有没有东西,再继续睡眠。而是你在整个period期间都在积极等待,有东西被放入队列,这样你就可以在等待'!STOP!'到来时,偶尔做点其他事情。这里没有什么隐藏的陷阱;get_nowait内部使用time.time()加上period来决定等待多长时间:1)为了能够获取队列的内部锁,2)为了确保队列里确实有东西可以取。以下是来自multprocessing/queues.py的相关代码:

    if block:
        deadline = time.time() + timeout
    if not self._rlock.acquire(block, timeout): # Waits for up to `timeout` to get the lock
        raise Empty # raise empty if it didn't get it
    try:
        if block:
            timeout = deadline - time.time()
            if timeout < 0 or not self._poll(timeout): # Once it has the lock, waits for however much time is left before `deadline` to something to arrive
                raise Empty
        elif not self._poll():
            raise Empty
        res = self._recv()
        self._sem.release()
        return res 
    finally:
        self._rlock.release()

撰写回答