Python同时运行两个循环,一个循环是一个速率有限的,并且取决于另一个循环



我在Python中有一个问题,我想同时运行两个循环。我觉得我需要这样做,因为第二个循环需要受到限制,但是第一个循环确实不应该受到限制。另外,第二个循环从第一个循环进行输入。

我正在寻找像这样有效的东西:

for line in file:
do some stuff
list = []
list.append("an_item")
Rate limited:
for x in list:
do some stuff simultaneously

有两种基本方法,具有不同的权衡:在任务之间同步切换,并且在线程或子过程中运行。首先,一些常见的设置:

from queue import Queue # or Queue, if python 2
work = Queue()
def fast_task():
    """ Do the fast thing """
    if done:
        return None
    else:
        return result
def slow_task(arg):
    """ Do the slow thing """
RATE_LIMIT = 30 # seconds

现在,同步方法。它具有更简单,更易于调试的优点,以较慢的成本。慢的程度取决于您的任务细节。它的工作方式是,我们运行一个紧密的循环,每次都会调用快速工作,并且只有在足够的时间过去时才能做缓慢的工作。如果快速工作不再产生工作,并且队列为空,我们退出。

import time
last_call = 0
while True:
    next_job = fast_task()
    if next_job:
        work.put(next_job)
    elif work.empty():
        # nothing left to do
        break
    else:
        # fast task has done all its work - short sleep to slow the spin
        time.sleep(.1)
    now = time.time()
    if now - last_call > RATE_LIMIT:
        last_call = now
        slow_task(work.get())

如果您觉得这样的工作不够快,可以尝试multiprocessing方法。您可以使用相同的结构来处理线程或过程,具体取决于您是从multiprocessing.dummy还是multiprocessing本身导入的。我们使用multiprocessing.Queue进行通信而不是queue.Queue

def do_the_fast_loop(work_queue):
    while True:
        next_job = fast_task()
        if next_job:
            work_queue.put(next_job)
        else:
            work_queue.put(None) # sentinel - tells slow process to quit
            break
def do_the_slow_loop(work_queue):
    next_call = time.time()
    while True:
        job = work_queue.get()
        if job is None: # sentinel seen - no more work to do
            break
        time.sleep(max(0, next_call - time.time()))
        next_call = time.time() + RATE_LIMIT
        slow_task(job)
if __name__ == '__main__':
    # from multiprocessing.dummy import Queue, Process # for threads
    from multiprocessing import Queue, Process # for processes
    work = Queue()
    fast = Process(target=fast_task, args=(work,))
    slow = Process(target=slow_task, args=(work,))
    fast.start()
    slow.start()
    fast.join()
    slow.join()

您可以看到,您可以实现更多的机械,但是它会更快。同样,多少速度在很大程度上取决于您的任务。我会尝试所有三种方法 - 同步,螺纹和多进程 - 看看您最喜欢哪种方法。

您需要做2件事:

  1. 将功能置于其自己的过程中需要数据
  2. 实施一种在两个过程之间进行交流的方法(例如队列(

所有这些都必须归功于GIL。

相关内容

  • 没有找到相关文章

最新更新