I want understand how to correctly structure a functional asyncio-based program.
The code below wraps two external APIs to provide the client a simple send_weather()
function. Its structure reflects my current understanding of ansynchronous programming and the very little I've grasped of functional programming.
import asyncio
from functools import partial
import aiohttp
SUCCESSFUL_PUSH = {'deleted': True} # Value specific to fake push service
async def _post(headers, url, data):
async with aiohttp.ClientSession(headers=headers) as session:
async with session.post(url, json=data, verify_ssl=False) as response:
return await response.json()
async def _get(headers, url):
async with aiohttp.ClientSession(headers=headers) as session:
async with session.get(url, verify_ssl=False) as response:
return await response.json()
def make_comms(headers):
get = partial(_get, headers)
post = partial(_post, headers)
return get, post
async def _notify(post, message, user):
url = f"https://api.keen.io/dev/null?user={user}" # Fake push service
return await post(url, message)
async def _find_city(get, city):
url = f"https://www.metaweather.com/api/location/search?query={city}"
obj_list = await get(url)
if obj_list:
return obj_list[0]
return None
async def _city_weather(get, city_id):
url = f"https://www.metaweather.com/api/location/{city_id}"
return await get(url)
async def _send_weather(get, post, city, user):
city_data = await _find_city(get, city)
if city_data is None:
print("Could not find city")
return
forecast_data = await _city_weather(get, city_data["woeid"])
weather = forecast_data["consolidated_weather"][0]["weather_state_name"]
message = f"Current weather in {city}: {weather}"
reply = await _notify(post, {"message": message}, user)
if reply == SUCCESSFUL_PUSH:
print(f"Current weather in {city}: {weather}")
else:
print(f"Push notification to {user} failed: {reply}")
def init(get, post):
return partial(_send_weather, get, post)
if __name__ == "__main__":
HEADERS = {"Content-Type": "application/json"}
get, post = make_comms(HEADERS)
send_weather = init(get, post)
asyncio.run(send_weather("Glasgow", "Bob"))
How to structure an asynchronous functional program?