您可以使用第二種形式的調用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