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)
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
__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
on a function it means that "calling" that function now returns a value of type
__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