"Ian Kelly" wrote in message news:calwzidngogpx+cpmvba8vpefuq4-bwmvs0gz3shb0owzi0b...@mail.gmail.com...

On Sat, Jan 23, 2016 at 7:38 AM, Frank Millman <fr...@chagford.com> wrote:
> Here is the difficulty. The recommended way to handle a blocking > operation > is to run it as task in a different thread, using run_in_executor(). > This > method is a coroutine. An implication of this is that any method that > calls
> it must also be a coroutine, so I end up with a chain of coroutines
> stretching all the way back to the initial event that triggered it.

This seems to be a common misapprehension about asyncio programming.
While coroutines are the focus of the library, they're based on
futures, and so by working at a slightly lower level you can also
handle them as such. So  while this would be the typical way to use
run_in_executor:

async def my_coroutine(stuff):
    value = await get_event_loop().run_in_executor(None,
blocking_function, stuff)
    result = await do_something_else_with(value)
    return result

This is also a perfectly valid way to use it:

def normal_function(stuff):
    loop = get_event_loop()
    coro = loop.run_in_executor(None, blocking_function, stuff)
    task = loop.create_task(coro)
    task.add_done_callback(do_something_else)
    return task

I am struggling to get my head around this.

1. In the second function, AFAICT coro is already a future. Why is it necessary to turn it into a task? In fact when I tried that in my testing, I got an assertion error -

File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
   task = tasks.Task(coro, loop=self)
File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
   assert coroutines.iscoroutine(coro), repr(coro)
AssertionError: <Future pending ... >

2. In the first function, calling 'run_in_executor' unblocks the main loop so that it can continue with other tasks, but the function itself is suspended until the blocking function returns. In the second function, I cannot see how the function gets suspended. It looks as if the blocking function will run in the background, and the main function will continue.

I would like to experiment with this further, but I would need to see the broader context - IOW see the 'caller' of normal_function(), and see what it does with the return value.

I feel I am getting closer to an 'aha' moment, but I am not there yet, so all info is appreciated.

Frank


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to