Python使用带有loop_forever的期货

时间:2016-07-02 14:35:54

标签: python python-3.x python-asyncio

刚开始尝试asynch看起来非常酷。我试图将期货用于永远运行的异步协程,但我收到了这个错误:

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()

2 个答案:

答案 0 :(得分:2)

无限期地调用

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 +,则可以使用新语法(asyncawait):

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()))

答案 1 :(得分:1)

关注@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()