Python 与 loop_forever 一起使用期货
Python using futures with loop_forever
刚开始尝试异步,看起来很酷。我正在尝试将 futures 与永远运行的异步协程一起使用,但出现此错误:
Task exception was never retrieved
future: <Task finished coro=<slow_operation() done, defined at ./asynchio-test3.py:5> exception=InvalidStateError("FINISHED: <Future finished result='This is the future!'>",)>
这是我的代码,如果我删除与期货相关的 3 行,它会按预期运行:
import asyncio
@asyncio.coroutine
def slow_operation():
yield from asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.async(slow_operation())
def got_result(future):
print(future.result())
loop = asyncio.get_event_loop()
future = asyncio.Future()
future.add_done_callback(got_result)
asyncio.async(slow_operation())
try:
loop.run_forever()
finally:
loop.close()
slow_operator
被无限期地调用,多次为同一个未来对象调用set_result
;这是不可能的。
>>> import asyncio
>>> future = asyncio.Future()
>>> future.set_result('result')
>>> future.set_result('result')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python35\lib\asyncio\futures.py", line 329, in set_result
raise InvalidStateError('{}: {!r}'.format(self._state, self))
asyncio.futures.InvalidStateError: FINISHED: <Future finished result='result'>
为每个 slow_operator
调用创建新的未来。例如:
@asyncio.coroutine
def slow_operation(future):
yield from asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.async(slow_operation(new_future()))
def got_result(future):
print(future.result())
def new_future():
future = asyncio.Future()
future.add_done_callback(got_result)
return future
loop = asyncio.get_event_loop()
asyncio.async(slow_operation(new_future()))
try:
loop.run_forever()
finally:
loop.close()
顺便说一句,如果您使用的是 Python 3.5+:
,则可以使用新语法 (async
, await
)
async def slow_operation(future):
await asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.ensure_future(slow_operation(new_future()))
按照@falsetru 的回答,这是一个完整的程序,有 3 个异步协程,每个协程都有自己的 got_result 函数。我使用的是 v3.4,所以这就是我不使用新语法的原因。作为一个有趣的副作用,输出清楚地展示了协程的单线程特性。我希望它可以作为某人的模板:
import asyncio
@asyncio.coroutine
def task1(future):
yield from asyncio.sleep(1)
print ("This is operation#1")
future.set_result('This is the result of operation #1!')
asyncio.async(task1(new_future(got_result1)))
def got_result1(future):
print(future.result())
@asyncio.coroutine
def task2(future):
yield from asyncio.sleep(1)
print ("This is operation#2")
future.set_result('This is the result of operation #2!')
asyncio.async(task2(new_future(got_result2)))
def got_result2(future):
print(future.result())
@asyncio.coroutine
def task3(future):
yield from asyncio.sleep(1)
print ("This is operation#3")
future.set_result('This is the result of operation #3!')
asyncio.async(task3(new_future(got_result3)))
def got_result3(future):
print(future.result())
def new_future(callback):
future = asyncio.Future()
future.add_done_callback(callback)
return future
tasks = [task1(new_future(got_result1)),
task2(new_future(got_result2)),
task3(new_future(got_result3))]
loop = asyncio.get_event_loop()
for task in tasks:
asyncio.async(task)
try:
loop.run_forever()
finally:
loop.close()
刚开始尝试异步,看起来很酷。我正在尝试将 futures 与永远运行的异步协程一起使用,但出现此错误:
Task exception was never retrieved
future: <Task finished coro=<slow_operation() done, defined at ./asynchio-test3.py:5> exception=InvalidStateError("FINISHED: <Future finished result='This is the future!'>",)>
这是我的代码,如果我删除与期货相关的 3 行,它会按预期运行:
import asyncio
@asyncio.coroutine
def slow_operation():
yield from asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.async(slow_operation())
def got_result(future):
print(future.result())
loop = asyncio.get_event_loop()
future = asyncio.Future()
future.add_done_callback(got_result)
asyncio.async(slow_operation())
try:
loop.run_forever()
finally:
loop.close()
slow_operator
被无限期地调用,多次为同一个未来对象调用set_result
;这是不可能的。
>>> import asyncio
>>> future = asyncio.Future()
>>> future.set_result('result')
>>> future.set_result('result')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python35\lib\asyncio\futures.py", line 329, in set_result
raise InvalidStateError('{}: {!r}'.format(self._state, self))
asyncio.futures.InvalidStateError: FINISHED: <Future finished result='result'>
为每个 slow_operator
调用创建新的未来。例如:
@asyncio.coroutine
def slow_operation(future):
yield from asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.async(slow_operation(new_future()))
def got_result(future):
print(future.result())
def new_future():
future = asyncio.Future()
future.add_done_callback(got_result)
return future
loop = asyncio.get_event_loop()
asyncio.async(slow_operation(new_future()))
try:
loop.run_forever()
finally:
loop.close()
顺便说一句,如果您使用的是 Python 3.5+:
,则可以使用新语法 (async
, await
)
async def slow_operation(future):
await asyncio.sleep(1)
print ("This is the task!")
future.set_result('This is the future!')
asyncio.ensure_future(slow_operation(new_future()))
按照@falsetru 的回答,这是一个完整的程序,有 3 个异步协程,每个协程都有自己的 got_result 函数。我使用的是 v3.4,所以这就是我不使用新语法的原因。作为一个有趣的副作用,输出清楚地展示了协程的单线程特性。我希望它可以作为某人的模板:
import asyncio
@asyncio.coroutine
def task1(future):
yield from asyncio.sleep(1)
print ("This is operation#1")
future.set_result('This is the result of operation #1!')
asyncio.async(task1(new_future(got_result1)))
def got_result1(future):
print(future.result())
@asyncio.coroutine
def task2(future):
yield from asyncio.sleep(1)
print ("This is operation#2")
future.set_result('This is the result of operation #2!')
asyncio.async(task2(new_future(got_result2)))
def got_result2(future):
print(future.result())
@asyncio.coroutine
def task3(future):
yield from asyncio.sleep(1)
print ("This is operation#3")
future.set_result('This is the result of operation #3!')
asyncio.async(task3(new_future(got_result3)))
def got_result3(future):
print(future.result())
def new_future(callback):
future = asyncio.Future()
future.add_done_callback(callback)
return future
tasks = [task1(new_future(got_result1)),
task2(new_future(got_result2)),
task3(new_future(got_result3))]
loop = asyncio.get_event_loop()
for task in tasks:
asyncio.async(task)
try:
loop.run_forever()
finally:
loop.close()