So I'm trying to port a code to work with Asyncio.
My problem are the @property
s, which - if not yet cached - need a network request to complete.
While I can await them without a problem in most contexts using that property in the __str__
method fails which is kinda expected.
What is the most pythonic way to solve this, other than caching the value on instance creation or just not using Asyncio.
Here is a example code illustrating the issue:
import requests
from typing import Union
class Example(object):
_username: Union[str, None]
@property
def username(self):
if not _username:
r = request.get('https://api.example.com/getMe')
self._username = r.json()['username']
return self._username
def __str__(self):
return f"Example(username={self.username!r})"
e = Example()
str(e)
So far I could come up with the following.
I could substitute @property
with @async_property
(
PyPi, Github, Docs),
and requests
with httpx
(PyPi, Github, Docs).
However it is still not working.
My attempt at porting it to Asyncio:
import httpx
from typing import Union
from async_property import async_property
class Example(object):
_username: Union[str, None]
@async_property
async def username(self):
if not _username:
async with httpx.AsyncClient() as client:
r = await client.get('https://www.example.org/')
self._username = r.json()['username']
return self._username
async def __str__(self):
return f"Example(username={await self.username!r})"
e = Example()
str(e)
Fails with TypeError: __str__ returned non-string (type coroutine)
.