Let us suppose we have a class with a property that can only be setted asynchronously. Is there a way to make this work without explicitly calling a setter ?
MNWE:
import asyncio
loop = asyncio.get_event_loop()
class AsyncTest:
def __init__(self, attrib):
self._attrib = attrib
@property
def attrib(self):
return self._attrib
@attrib.setter
async def set_attrib(self, attrib):
await asyncio.sleep(1.0)
self._attrib = attrib
async def main():
t = AsyncTest(1)
print(t.attrib)
await t.attrib = 3
print(t.attrib)
asyncio.ensure_future(main())
loop.run_forever()
This fails with
File "asyncprop.py", line 22
await t.attrib = 3
^
SyntaxError: can't assign to await expression
which is not surprising, given that the grammar for await
is
await ::= ["await"] primary
So it seems we are bound to forget this nice @property
and resign ourselves to using getters and setters for asynchronous operations. Did I miss something?
You can use the async-property
package: https://pypi.org/project/async-property/
Example:
from async_property import async_property
class Foo:
@async_property
async def remote_value(self):
return await get_remote_value()
f = Foo()
await f.remote_value
You can't nest a statement inside another statement; assignment is a statement, and so is await
. You could use setattr()
to set attributes in an expression:
await setattr(t, 'attrib', 3)
However, a property
wraps the setter in a way that does not support async
methods (they are not awaitable), so you are still better off with an explicit setter method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With