我正在开发一种工具来抓取推文并对其进行处理,以便用户构建一个词频分析。由于需要处理大量数据,我将文字处理部分与推文抓取部分分开。
multiprocessing.Connection
(rec, sen = multiprocessing.Pipe(False)
)提供了一个在流程之间传输数据的有用工具。但是,当发送端显式调用Connection.close()
时,我找不到接收端何时到达EOF的实用程序。我试过了:
def yielder(conn):
yield conn.recv()
但是在仅返回管道中的第一个项目之后,这会以某种方式停止。
我目前在while True
循环中使用Try-Except语句绕过了这个问题:
try:
status = rec.recv()
...process data...
except BrokenPipeError:
break
我还可以看到这是通过发送一个特定的结束标记来完成的,让接收端在接收到它时终止进程。但这些都是非常反直觉和丑陋的方式,违反了Python的禅宗:
美丽胜过丑陋。
...
应该有一个 - 最好只有一个 - 显而易见的方法。
我错过了什么吗?是否有简单,优雅的方式,如c ++的
while getline(istreamobject, line)
执行我的任务?
答案 0 :(得分:0)
您可以使用调用iter
的第二种形式:iter(callable, sentinel) -> iterator
将其转换为for循环。你仍然必须抓住异常。
try:
for status in iter(conn.recv, None):
...
except BrokenPipeError:
pass
如果不是关闭管道,而是向管道发送“eof”,您可以删除try/except
并执行for status in iter(conn.recv, 'EOF message')
,并在收到'EOF message'
时(可以是任何内容) ),iter
停止for循环。通常EOF消息是一个空字符串,因此通常会看到如下内容:
for line in iter(file.read, ''):
...
itertools recipes将此功能称为iter_except
。这基本上是您之前使用yielder
函数
def iter_except(func, exception, first=None):
""" Call a function repeatedly until an exception is raised.
Converts a call-until-exception interface to an iterator interface.
Like builtins.iter(func, sentinel) but uses an exception instead
of a sentinel to end the loop.
Examples:
iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator
iter_except(d.popitem, KeyError) # non-blocking dict iterator
iter_except(d.popleft, IndexError) # non-blocking deque iterator
iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue
iter_except(s.pop, KeyError) # non-blocking set iterator
"""
try:
if first is not None:
yield first() # For database APIs needing an initial cast to db.first()
while True:
yield func()
except exception:
pass
所以,你也可以这样做:
for status in iter_except(conn.recv, BrokenPipeError):
...
或者只是修复yielder
功能:
def yielder(conn):
try:
while True:
yield conn.recv()
except BrokenPipeError:
pass
for status in yielder(conn):
...