Python コルーチンの内部実装(send, throw, close)
コルーチンは send, throw, close メソッドで外部から制御できます。これらを使うと、双方向通信やエラーハンドリングが可能になります。
send:値を送り込む
yield 式は値を受け取れます。send で値を渡すと、yield 式の評価結果になります。
def accumulator():
total = 0
while True:
value = yield total
if value is None:
break
total += value
coro = accumulator()
next(coro) # ジェネレータを起動(最初の yield まで進む)
print(coro.send(10)) # 10
print(coro.send(20)) # 30
print(coro.send(5)) # 35
最初の next() は send(None) と同等で、ジェネレータを最初の yield まで進めます。
throw:例外を投入する
throw でコルーチン内部に例外を発生させられます。
def coro_with_error_handling():
try:
while True:
value = yield
print(f"Received: {value}")
except ValueError as e:
print(f"Error handled: {e}")
yield "recovered"
c = coro_with_error_handling()
next(c)
c.send(1) # Received: 1
result = c.throw(ValueError, "something wrong")
print(result) # recovered
close:コルーチンを終了する
close は GeneratorExit を投入してコルーチンを終了させます。
def resource_manager():
print("Acquiring resource")
try:
while True:
yield
finally:
print("Releasing resource")
c = resource_manager()
next(c) # Acquiring resource
c.close() # Releasing resource
finally ブロックでクリーンアップ処理が実行されます。
状態マシンの実装例
def state_machine():
state = "IDLE"
while True:
event = yield state
if state == "IDLE" and event == "start":
state = "RUNNING"
elif state == "RUNNING" and event == "stop":
state = "IDLE"
sm = state_machine()
print(next(sm)) # IDLE
print(sm.send("start")) # RUNNING
print(sm.send("stop")) # IDLE
send, throw, close を活用すると、コルーチンを協調的なタスクとして柔軟に制御できます。