Asyncio Part the third
Posted on Mon 13 August 2018 in Posts
I found this interesting and gave a small bit of insight/help with forming my mental model around asyncio. Let's say you have a class:
import asyncio
class Foo:
def __init__(self, loop):
print("in foo init")
loop.run_until_complete(self.consumer())
async def consumer(self):
print("in consumer")
def main():
loop = asyncio.get_event_loop()
f = Foo(loop)
if __name__ == "__main__":
main()
This is perfectly fine. Nothing wrong with calling some async code from your (synchronous)
__init__
method.
What happens though if you make your __init__
async though?
... same from before ...
class Foo:
async def __init__(self, loop):
print("in foo init")
await self.consumer()
... rest same as before ...
When you run this, you'll find you get an error:
Traceback (most recent call last):
File "/Users/ad0418340/temp/sandbox/interac/paymentdispatch/test5.py", line 20, in <module>
main()
File "/Users/ad0418340/temp/sandbox/interac/paymentdispatch/test5.py", line 16, in main
f = Foo(loop)
TypeError: __init__() should return None, not 'coroutine'
As it turns out, this is the same exception that gets thrown anytime you return
a value
from __init__
. For example:
class Foo:
def __init__(self):
return 42 # this will blow up with a TypeError
What can we take from this? A coroutine is a type of value. As soon as you put async
on a function it means that "calling" that function now returns a value of type coroutine
.
Since __init__
methods can't return values in Python (it'd be nonsensical to do so, think
about how you'd possibly get the value from a return), you can't make your __init__
methods
async
.