sentinelhub-py
sentinelhub-py copied to clipboard
[FEAT] python async support
What is the problem? Please describe.
I wish to be able to interact with sentinelhub via the python libraries asynchronously
Here's the solution
I've written up an async harness I have been using to work with the SentinelHub classes, maybe it can provide some inspiration.
from sentinelhub import SHConfig
from cache import AsyncTTL
import httpx
from urllib.parse import urlencode
@AsyncTTL(time_to_live=60*45) # 45m in sec
async def get_sentinel_token(config: SHConfig) -> str:
params = urlencode({
'grant_type':'client_credentials',
'client_id': config.sh_client_id,
'client_secret': config.sh_client_secret,
})
url = f'{config.sh_auth_base_url}/oauth/token?{params}'
headers = {
"content-type": "application/x-www-form-urlencoded"
}
async with httpx.AsyncClient() as client:
r = await client.post(url, headers=headers, timeout=10.0)
r.raise_for_status()
output = r.json()
return output.get('access_token')
async def sentinel_request_async(request: SentinelHubRequest, config: SHConfig) -> Union[dict, bytes]:
request.create_request() # populate the download list.
dl = request.download_list[0]
headers = dl.headers
async with httpx.AsyncClient() as client:
access_token = await get_sentinel_token(config, client)
headers['Authorization'] = f"Bearer {access_token}"
r = await client.post(dl.url, headers=headers, json=dl.post_values, timeout=30.0)
r.raise_for_status()
if r.headers.get('content-type') == 'application/json':
return r.json()
elif r.headers.get('content-type') == 'image/tiff':
return tiff.imread(BytesIO(r.read()))
else:
return r.read() # bytes
The important thing is to ensure any I/O in the chain is performed in an async context, including things like token retrieval or any other network I/O.
Hope this helps.
Hi @cmcconomyfwig thank you for the suggestion. Supporting async has been on our radar a couple of times in the past years. But since async is a rather all-or-nothing approach in Python, we never had the time to fully commit to it. We hope to be able to include async support in a future version, but cannot promise anything at this point.
Thanks for the reply, I understand that what I have above doesn't cover all the batch downloading capabilities you've built into the sync client, and it looks like quite the undertaking.
Whenever it is released, I look forward to transitioning to official APIs. In the meantime, I hope that others who are looking for any way to hook asynchronous calling into SentinelHub can make use of the snippet above.
Hi @zigaLuksic , I have been working with HTTPX Async for few months now, I'd be happy to work on this task if needed
Hi @zigaLuksic , I have been working with HTTPX Async for few months now, I'd be happy to work on this task if needed
we very much appreciate the offer. but the current issue is that the structure of the sh-py
is hard to adapt for such large changes. We do have a larger refactoring planned, and hopefully after that we would be able to start with async.
Hi @zigaLuksic , I have been working with HTTPX Async for few months now, I'd be happy to work on this task if needed
we very much appreciate the offer. but the current issue is that the structure of the
sh-py
is hard to adapt for such large changes. We do have a larger refactoring planned, and hopefully after that we would be able to start with async.
Thanks a lot for getting back, let me know if you need me on any other task, I'm available for contribution on GIS | Python | Documentation