【问题标题】:running two interdependent while loops in python?在python中运行两个相互依赖的while循环?
【发布时间】:2017-02-09 13:08:53
【问题描述】:

对于网络抓取分析,我需要两个永久运行的循环,一个返回一个包含每 x 分钟更新一次的网站的列表,而另一个每 y 秒分析一次网站(旧的和新的)。这是示例的代码构造,我正在尝试做,但它不起作用:代码已被编辑以包含答案和我的研究

from multiprocessing import Process
import time, random

from threading import Lock
from collections import deque

class MyQueue(object):
    def __init__(self):
        self.items = deque()
        self.lock = Lock()

    def put(self, item):
        with self.lock:
            self.items.append(item)
# Example pointed at in [this][1] answer
    def get(self):
        with self.lock:
            return self.items.popleft()

def a(queue):
    while True:
        x=[random.randint(0,10), random.randint(0,10), random.randint(0,10)]
        print 'send', x
        queue.put(x)
        time.sleep(10)


def b(queue):
    try:
        while queue:
            x = queue.get()
            print 'recieve', x
            for i in x:
                print i
            time.sleep(2)
    except IndexError:
        print queue.get()   



if __name__ == '__main__':
    q = MyQueue()
    p1 = Process(target=a, args=(q,))
    p2 = Process(target=b, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

所以,这是我在完成在线介绍课程后的第一个 Python 项目,我在这里苦苦挣扎。我现在明白了,这些函数并没有真正并行运行,因为 b 直到 a 完成才开始(我用this 回答了一个修改了计时器的答案,而当真)。 编辑:即使使用了答案中给出的方法,我认为情况仍然如此,因为queue.get() 抛出一个 IndexError 说,双端队列是空的。我只能用没有完成的过程来解释,因为当我打印 queue.get() 紧跟在 .put(x) 之后它不为空。

我最终想要这样的输出:

send [3,4,6]
3
4
6
3
4
send [3,8,6,5] #the code above gives always 3 entries, but in my project 
3              #the length varies
8
6
5
3
8
6
.
.

如果有两个真正并行的循环,其中一个每 x 分钟返回一个更新列表,另一个循环需要作为分析的基础,我需要什么? Process 真的是正确的工具吗? 我在哪里可以获得关于设计我的程序的好信息。

【问题讨论】:

  • Thread 绝对是您问题的最简单答案!这可能很可怕,但在 Python 中很容易做到
  • @Lordofdark 我也会接受这个建议并阅读线程!谢谢。

标签: python while-loop parallel-processing


【解决方案1】:

不久前我做了一些类似的事情。我认为使用 Process 是正确的方法,但是如果您想在进程之间传递数据,那么您可能应该使用 Queue。

https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes

首先创建队列并将其传递给两个进程。一个可以写入,另一个可以读取。

我记得的一个问题是,读取过程会阻塞队列,直到有东西被推送到它,所以当进程 1 完成时,您可能需要将某种特殊的“终止”消息推送到队列,以便进程 2知道停下来。

编辑:简单的例子。这不包括停止进程的干净方法。但它展示了如何启动 2 个新进程并将数据从一个进程传递到另一个进程。由于 get() 函数 b 上的队列块将在继续之前自动等待来自 a 的数据。

from multiprocessing import Process, Queue
import time, random

def a(queue):
    while True:
        x=[random.randint(0,10), random.randint(0,10), random.randint(0,10)]
        print 'send', x
        queue.put(x)
        time.sleep(5)


def b(queue):
    x = []
    while True:
        time.sleep(1)
        try:
            x = queue.get(False)
            print 'receive', x
        except:
            pass
        for i in x:
            print i


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=a, args=(q,))
    p2 = Process(target=b, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

【讨论】:

  • 首先感谢您的帮助。我一直在阅读队列并尝试使用它。不过,我无法让您的示例起作用。我得到一个TypeError: 'Queue' object is not iterable。不是 q=Queue.Queue() 还是缺少什​​么?我在一个例子中看到了这一点。
  • 抱歉,我犯了一些小错误。我已经更新了示例,这次实际运行了代码。
  • 这真是太好了!但是我还有一个大问题:你的代码只打印一次i in xfor i in x 前面的 while 循环连续打印出来,但不接受新的 queue.get()。所以我得到receive [new list]print i 仍然打印旧列表。在我的现实生活项目中,功能 1 提供了一个不断变化的 URL 列表,功能 2 需要不断分析该列表,以“接受”列表中的新输入。什么是正确的结构?
  • 我更新了答案。解决方案是告诉 queue.get 调用不要阻塞。如果队列中没有任何内容,它将引发错误,您可以捕获并处理(通过忽略它并继续现有数据)
  • 我的回答假设您正在使用多处理模块中的特殊队列,该模块已经是进程/线程安全并包含必要的功能。
猜你喜欢
  • 2011-09-18
  • 2013-10-21
  • 2017-10-14
  • 2020-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
相关资源
最近更新 更多