Ruslan  Galimov
Ruslan Galimov

Reputation: 256

First experience with asyncio

I am learning python-asyncio, and I'm trying to write a simple model.

I have a function handling tasks. While handling, it goes to another remote service for data and then prints a message.

My code:

dd = 0

@asyncio.coroutine
def slow_operation():
    global dd
    dd += 1
    print('Future is started!', dd)
    yield from asyncio.sleep(10 - dd)  # request to another server
    print('Future is done!', dd)

def add():
    while True:
        time.sleep(1)
        asyncio.ensure_future(slow_operation(), loop=loop)

loop = asyncio.get_event_loop()
future = asyncio.Future()
asyncio.ensure_future(slow_operation(), loop=loop)
th.Thread(target=add).start()
loop.run_forever()

But this code doesn't switch the context while sleeping in:

yield from asyncio.sleep(10 - dd)

How can I fix that?

Upvotes: 1

Views: 445

Answers (1)

Vincent
Vincent

Reputation: 13415

asyncio.ensure_future is not thread-safe, that's why slow_operation tasks are not started when they should be. Use loop.call_soon_threadsafe:

    callback = lambda: asyncio.ensure_future(slow_operation(), loop=loop)
    loop.call_soon_threadsafe(cb)

Or asyncio.run_coroutine_threadsafe if you're running python 3.5.1:

    asyncio.run_coroutine_threadsafe(slow_operation(), loop)

However, you should probably keep the use of threads to the minimum. Unless you use a library running tasks in its own thread, all the code should run inside the event loop (or inside an executor, see loop.run_in_executor).

Upvotes: 3

Related Questions