I'm trying to correct my async func to work with this script:
import asyncio
import platform
import aiohttp
if platform.system() == 'Windows':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
url = 'https://services.rappi.com.br/api/ms/web-proxy/dynamic-list/cpgs/'
req_headers = {'authority': 'services.rappi.com.br', 'accept': 'application/json',
'authorization': 'Bearer ft.gAAAAABjMbGKkc2fkTMa2M2EKuBrCM1Z1vU5Ww1Fw03CjpJEb9UF1DO1TAjwpAD0H0NIImuMjWFcOkUURseLzJIi0DNSOr-oRWcZWgcnHLm2Ed6rDLvxQ2ikdGLtyVXZRqgGHWOMlBPVSKjYLb6NMZmAeHhAsGNjiQ3vP5VEdb_ULA9S5Lpo8H7-ElhKufmlVqQ6CrDyTUsyQeZ3IzbNCbN8MBLFhgRxVMZSwyl640YXF9ZvQUI1sibP-Ko86xrin_2EXEmAdEk7aSl9u0ezlmnBL6Wk8a7CwSJUEUAwAjrNdJTLSodjQaiVVx7TZ0rQEkzPgceaH7wtpmvl--6txmRDnBu4g0na3Km19K1LNzs0fz7-_Go8Qlg=',
'deviceid': '957933bd-cdc4-4876-ad00-bc00a1d55c29',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'}
json_data = {"dynamic_list_request":
{
"limit": 100, "offset": 0, "context": "sub_aisles",
"state": {"lat": "-23.5516221", "lng": "-46.7404627"}
},
"dynamic_list_endpoint": "context/content",
"proxy_input":
{
"seo_friendly_url": "900597707-assai-atacadista-super-sao-paulo",
"aisle_friendly_url": "",
}
}
json_data2 = {"dynamic_list_request":
{
"limit": 100, "offset": 0, "context": "aisle_detail",
"state": {"lat": "-23.5516221", "lng": "-46.7404627"}
},
"dynamic_list_endpoint": "context/content",
"proxy_input":
{
"seo_friendly_url": "900597707-assai-atacadista-super-sao-paulo",
"aisle_friendly_url": "bebidas",
'subaisle_friendly_url': ""
}
}
market_list = ['900597707-assai-atacadista-super-sao-paulo', '900520986-makro-atacadista-sao-paulo']
data = [{'sub_category': 'temperos-e-molhos', 'category': 'mercearia'},
{'sub_category': 'massas', 'category': 'mercearia'}]
async def fetch(url, session):
list_items = []
global data
for cats in data: # 1) >> how to pass here to ASYNC? <<
json_data2['proxy_input']['subaisle_friendly_url'] = cats['sub_category']
json_data2['proxy_input']['aisle_friendly_url'] = cats['category']
for markets in market_list: # 2) >> how to pass here to ASYNC? <<
json_data2['proxy_input']['seo_friendly_url'] = markets
print((json_data2['proxy_input']['subaisle_friendly_url'], json_data2['proxy_input']['aisle_friendly_url'],
json_data2['proxy_input']['seo_friendly_url']))
async with session.post(url, headers=req_headers, json=json_data2) as response:
try:
json_body = await response.json()
json_body = json_body['dynamic_list_response']['data']['components']
except KeyError:
json_body = None
if json_body is not None:
for sections in json_body:
for items in sections['resource']['products']:
list_items.append(items)
return list_items
async def main():
tasks = []
async with aiohttp.ClientSession() as session:
tasks.append(
asyncio.create_task(fetch(url, session))
)
body = await asyncio.gather(*tasks)
return body
print(asyncio.run(main()))
I know the for loops above my session.post aren't working because they aren't async, how can I get those corrected? I already tried a bunch of things, but they didn't work.
async with session.post(url, headers=req_headers, json=json_data2) as response:
Obs: The code is working, you can run and test it if you want.
- The whole code can be changed, if needed, I don't mind...
CodePudding user response:
In order to achieve asyncio paralelism, the body of the inner for
loop should be refactored into another co-routine which can run as an indepedent task. In this way, the asyncio mainloop can orchestrate the various calls in parallel:
The code bellow could become a bit more elegant by feeding the tasks continuosly with the "cats", and letting some tasks go running in parallel using asyncio.wait
instead of gather
. The "easy" refactoring is just putting all calls for a single category in a task list and gather those:
[untested]
async def fetch_items(session, markets):
local_items = []
json_data2['proxy_input']['seo_friendly_url'] = markets
print((json_data2['proxy_input']['subaisle_friendly_url'], json_data2['proxy_input']['aisle_friendly_url'],
json_data2['proxy_input']['seo_friendly_url']))
async with session.post(url, headers=req_headers, json=json_data2) as response:
try:
json_body = await response.json()
json_body = json_body['dynamic_list_response']['data']['components']
except KeyError:
return
for sections in json_body:
local_items.extend(items for items in sections['resource']['products'])
return local_items
async def fetch(url, session):
list_items = []
global data
for cats in data:
json_data2['proxy_input']['subaisle_friendly_url'] = cats['sub_category']
json_data2['proxy_input']['aisle_friendly_url'] = cats['category']
pending_tasks = [asyncio.create_task(fetch_items(session, markets)) for markets in market_list]
for result in await asyncio.gather(*pending_tasks):
list_items.extend(result)
return list_items
async def main():
tasks = []
async with aiohttp.ClientSession() as session: # there is no repetition here: no point in using .gather
body = await fetch(url. session)
return body