When creating a class which uses asyncio I've found myself in a situation where a property getter needs to make an io operation. Therefore the function should be a coroutine. However awaiting a property feels unusual.
Here is a minimal working of example of what I mean. The code is valid and runs.
import asyncio
class Person:
"""A class that represents a person"""
def __init__(self, forename, surname):
self.forename = forename
self.surname = surname
@property
async def fullname(self):
"""Perform an io operation and return something.
This could be looking something up in a database for example.
"""
await asyncio.sleep(0.1)
return f"{self.forename} {self.surname}"
async def main():
john = Person("John", "Smith")
# Let's print out the forename here, using the standard property format
print(john.forename)
# When printing the full name we must instroduce an await, which feels awkward.
print(await john.fullname)
# Start the loop and run the main function
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Is this the correct way of doing this?
Short answer: don't do this.
Longer answer: as mentionned in pep8:
Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.
So anything requiring IO is obviously not a candidate for a property. FWIW we don't only expect attributes access to be cheap, we also expect them to be safe (would you expect an attribute access to possibly raise an IOError, Database error, socket error or anything similar ?)
FWIW, you mention that "awaiting a property feels unusual" which should already answer you question. Actually and as far as I'm concerned, the mere idea of an "async property" strikes me as just totally insane - properties are (semantically) about the object's state, and I just can't make sense of the concept of "async state".
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