您可以使用第二种形式的调用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
停止的循环。通常情况下,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):
...
yielder函数不会抛出任何异常。它只是产生管道中的第一个值然后停止。 – flymousechiu
@flymousechiu它仍然只产生没有'while True'循环的第一个值吗? – Artyer
是的,如果你尝试下面的话,就可以明显看出来:'import multiprocessing as mp','def yielder(conn):yield conn.recv()','rec,sen = mp.Pipe(False)','for i in范围(10):sen.send(i)','list(yielder(rec))'。应该返回[0] – flymousechiu