I'm currently trying to do something like this:
import asyncio
class Dummy:
def method(self):
return 1
def __str__(self):
return "THIS IS A DUMMY CLASS"
async def start_doing():
asyncio.sleep(1)
return Dummy
async def do_something():
return start_doing().method()
async def main():
a = asyncio.create_task(do_something())
b = asyncio.create_task(do_something())
results = await asyncio.gather(a, b)
print(results)
asyncio.run(main())
But I get this error:
AttributeError: 'coroutine' object has no attribute 'method'
Which indicates that I cannot call my method on a coroutine object. One way to fix this is by doing these:
async def do_something():
return (await start_doing()).method()
But I think that by doing this you are inherently making your code synchronous. You are not generating a future, rather waiting for your work to be finished in do_something
and then proceed to the next item in the queue.
How should I call an object method in the future when the awaitable
has been awaited and my object is ready? how to schedule it to be called in the future?
Await the call then call the method on an instance of the returned class.
async def start_doing():
await asyncio.sleep(1)
return Dummy
async def do_something():
thing = await start_doing()
return thing().method()
How should I call an object method in the future when the awaitable has been awaited and my object is ready? how to schedule it to be called in the future?
See if I can get this correct.
do_something
it is scheduled.do_something
start.do_something
calls start_doing
and awaits it. do_something
is waiting the event loop takes control away from it and lets something else have a turn.start_doing
is scheduled, started, finishes waiting/sleeping, returns the object
do_something
is done waiting the event loop gives control/focus back to it.
I really don't know what the scheduling algorithm is, I think of it as a round-robin affair but it might be more intelligent than that.
To further extend on @wwii 's answer and address the concerns about risk of blocking using await
you can play with functions like the following f
:
import time
from datetime import datetime
import asyncio
start = datetime.now()
async def f(x, block_for=3):
print(f"{x} IN {ellapsed_time()}s")
time.sleep(block_for)
print(f"{x} AWAIT {ellapsed_time()}s")
await asyncio.sleep(x)
print(f"{x} OUT {ellapsed_time()}s")
def ellapsed_time():
return (datetime.now() - start).seconds
asyncio.create_task(f(2))
asyncio.create_task(f(1))
Which produces:
2 IN 0s
2 AWAIT 3s
1 IN 3s
1 AWAIT 6s
2 OUT 6s
1 OUT 7s
Until await
is called, f(2)
is blocking (preventing any other task from being scheduled). Once we call await
we explicitly inform the scheduler that we are waiting for something (usually I/O, but here simply "sleeping" ). Similarly, f(1)
blocks f(2)
from going out until it calls await
.
If we remove the blocking part (block for 0s) f(1)
will be rescheduled to execute before f(2)
and will therefore finish first:
>>> start = datetime.now()
>>> asyncio.create_task(f(2, block_for=0))
>>> asyncio.create_task(f(1, block_for=0))
2 IN 0s
2 AWAIT 0s
1 IN 0s
1 AWAIT 0s
1 OUT 1s
2 OUT 2s
Finally, about this part:
… how to schedule it to be called in the future?
You can have a look at how is asyncio.sleep() in python implemented? , it will probably help you understand better how asynchronous programming work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.