Reputation: 5152
Lets consider the following example of a class containing an asyncio loop and an async coroutine:
import asyncio
class Async:
def __init__(self):
self.loop=asyncio.get_event_loop()
async def function(self, word):
print(word)
await asyncio.sleep(1.0)
a=Async()
a.loop.run_until_complete(a.function("hello_world"))
This does work.
I would like to create a decorator so that i can simplify the syntax of the code calling function
to
a.function("hello_world")
I tried the following:
class Async:
def __init__(self):
self.loop=asyncio.get_event_loop()
def async_loop(f):
def decorated(*args, **kwargs):
self.loop.run_until_complete(f(*args, **kwargs))
@async_loop
async def function(self, word):
print(word)
await asyncio.sleep(1.0)
a=Async()
a.function("hello_world")
At that point i receive the error: 'NoneType' object is not callable
. - I also tried to have the decorator function outside of the class, but i got the same error. I'm not sure whether the decorator function best stands inside the claass (as a method) or outside.
I'm quite new to python so Asyncio, decorator, and decorators in classes are still quite confusing for me. Any good soul would have an idea how to do that code correctly?
Upvotes: 4
Views: 3156
Reputation: 63709
Decorators inside classes are a mess because self
has to creep in everywhere.
Here is a working version of your code:
import asyncio
class Async:
def __init__(self):
self.loop=asyncio.get_event_loop()
def async_loop(f):
def decorated(self, *args, **kwargs):
self.loop.run_until_complete(f(self, *args, **kwargs))
return decorated
@async_loop
async def function(self, word):
print(word)
await asyncio.sleep(1.0)
a=Async()
a.function("hello_world")
You can make it more "selfless" if you just declare the event loop inside async_loop, or even better, declare the decorator outside of the class:
def async_loop(f):
loop = asyncio.get_event_loop()
def decorated(*args, **kwargs):
loop.run_until_complete(f(*args, **kwargs))
return decorated
class Async:
@async_loop
async def function(self, word):
print(word)
await asyncio.sleep(1.0)
a=Async()
a.function("hello_world")
So now it starts to raise the question, "why is this in a class in the first place?" And another question, "isn't there a decorator out there that does this already?"
Upvotes: 6