import asyncio
import Response
import aiohttp
async def resolve_response_json(res):
new_res = Response()
async with res:
new_res.status = res.status
new_res.json = await res.json()
return new_res
class Client:
async def request(url):
async with aiohttp.ClientSession() as sess:
res = await sess.get(url=url)
return await resolve_response_json(res).json
client = Client()
loop = asyncio.get_event_loop()
value = loop.run_until_complete(client.request('https://example.com/api/v1/resource'))
Why does this piece of code give me:
> return await resolve_response_json(res).json
E AttributeError: 'coroutine' object has no attribute 'json'
I thought that the await keyword always returns an actual value. If it actually does, why is my code throwing this error?
Or am I just silly and probably forgot to put an await somewhere?
You are awaiting resolve_response_json(res).json, not resolve_response_json(res).
Change it to (await resolve_response_json(res)).json may work.
Related
Error AttributeError: module 'aiohttp' has no attribute 'ClientSession', But ClientSession exists in module, idk how to solve it. i tried everthing someone help
import aiohttp
import asyncio
import json
import time
async def get_page (session,url):
async with session.get(url) as r:
return await r.text()
async def get_all(session,urls) :
tasks = []
for url in urls:
task = asyncio.create_task(get_page(session,url) )
tasks.append(task)
results = await asyncio.gather(*tasks)
return results
async def main (urls) :
async with aiohttp.ClientSession() as session : # Error here
data = await get_all(session,urls)
return data
def parse(results):
for html in results:
data = json.loads(html)
return
if __name__ == '__main__':
urls = ['https://www.google.com']
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
results = asyncio.run(main(urls))
parse(results)
The problem is you've named the script aiohttp.py which interferes with python's ability to use the aiohttp module.
Rename that file to aiohttp_custom.py (or something else) and your problem should be gone.
this is my code i am trying to do 2 requests a get and a post with async i get this error now:
async with session.post(
AttributeError: 'str' object has no attribute 'post'
any idea how i can run 2 requests using async and parsing the data?
async def main():
async with aiohttp.ClientSession() as session:
async with session.get(
'https://login.yahoo.com',
) as login:
crumb = (await login.text()).partition('crumb" value="')[-1].partition('"')[0]
acrumb = (await login.text()).partition('name="acrumb" value="')[-1].partition('" />')[0]
session = (await login.text()).partition('sessionIndex" value="')[-1].partition('"')[0]
print(acrumb)
print(session)
print(crumb)
async with session.post(
'SECONDURL',
) as check:
print(await check.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())```
The issue is this line:
session = (await login.text()).partition('sessionIndex" value="')[-1].partition('"')[0]
You're overwriting your session variable with this variable also named session. I would change the variable name in the above line to something like:
session_index = (await login.text()).partition('sessionIndex" value="')[-1].partition('"')[0]
async def main():
# you create a variable named session here
async with aiohttp.ClientSession() as session:
...
# you're mistakenly overwriting the session variable here
session = (await login.text()).partition('sessionIndex" value="')[-1].partition('"')[0]
...
I am new to asynchronous programming in python, have been working on a script using aiohttp that fetches data from a get request and passes a specific variable from the response onto another post request. A sample of what I have tried is below:
async def fetch1(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp: # First hit to the url
data = resp.json() # Grab response
return await fetch2(data['uuid']) # Pass uuid to the second function for post request
async def fetch2(id):
url2 = "http://httpbin.org/post"
params = {'id': id}
async with aiohttp.ClientSession() as session:
async with session.post(url2,data=params) as resp:
return await resp.json()
async def main():
url = 'http://httpbin.org/uuid'
data = await fetch1(url)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
When I execute the script, I get the following error:
Traceback (most recent call last):
File ".\benchmark.py", line 27, in <module>
loop.run_until_complete(main())
File "C:\ProgramFiles\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2288.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File ".\benchmark.py", line 22, in main
data = await fetch1(url)
File ".\benchmark.py", line 10, in fetch1
return fetch2(data['uuid'])
TypeError: 'coroutine' object is not subscriptable
sys:1: RuntimeWarning: coroutine 'ClientResponse.json' was never awaited
I know that the coroutine is a generator, but how do I go ahead, any help will be appreciated.
The error says coroutine 'ClientResponse.json' was never awaited which means it must have an await before the json part. This is because you are using an async function.
async def fetch1(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp: # First hit to the url
data = await resp.json() # Grab response
return await fetch2(data['uuid']) # Pass uuid to the second function for post request
async def fetch2(id):
url2 = "http://httpbin.org/post"
params = {'id': id}
async with aiohttp.ClientSession() as session:
async with session.post(url2,data=params) as resp:
return await resp.json()
async def main():
url = 'http://httpbin.org/uuid'
data = await fetch1(url)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I am trying to achieve aiohttp async processing of requests that have been defined in my class as follows:
class Async():
async def get_service_1(self, zip_code, session):
url = SERVICE1_ENDPOINT.format(zip_code)
response = await session.request('GET', url)
return await response
async def get_service_2(self, zip_code, session):
url = SERVICE2_ENDPOINT.format(zip_code)
response = await session.request('GET', url)
return await response
async def gather(self, zip_code):
async with aiohttp.ClientSession() as session:
return await asyncio.gather(
self.get_service_1(zip_code, session),
self.get_service_2(zip_code, session)
)
def get_async_requests(self, zip_code):
asyncio.set_event_loop(asyncio.SelectorEventLoop())
loop = asyncio.get_event_loop()
results = loop.run_until_complete(self.gather(zip_code))
loop.close()
return results
When running to get the results from the get_async_requests function, i am getting the following error:
TypeError: object ClientResponse can't be used in 'await' expression
Where am i going wrong in the code? Thank you in advance
When you await something like session.response, the I/O starts, but aiohttp returns when it receives the headers; it doesn't want for the response to finish. (This would let you react to a status code without waiting for the entire body of the response.)
You need to await something that does that. If you're expecting a response that contains text, that would be response.text. If you're expecting JSON, that's response.json. This would look something like
response = await session.get(url)
return await response.text()
I am trying to teach myself Python's async functionality. To do so I have built an async web scraper. I would like to limit the total number of connections I have open at once to be a good citizen on servers. I know that semaphore's are a good solution, and the asyncio library has a semaphore class built in. My issue is that Python complains when using yield from in an async function as you are combining yield and await syntax. Below is the exact syntax I am using...
import asyncio
import aiohttp
sema = asyncio.BoundedSemaphore(5)
async def get_page_text(url):
with (yield from sema):
try:
resp = await aiohttp.request('GET', url)
if resp.status == 200:
ret_val = await resp.text()
except:
raise ValueError
finally:
await resp.release()
return ret_val
Raising this Exception:
File "<ipython-input-3-9b9bdb963407>", line 14
with (yield from sema):
^
SyntaxError: 'yield from' inside async function
Some possible solution I can think of...
Just use the #asyncio.coroutine decorator
Use threading.Semaphore? This seems like it may cause other issues
Try this in the beta of Python 3.6 for this reason.
I am very new to Python's async functionality so I could be missing something obvious.
You can use the async with statement to get an asynchronous context manager:
#!/usr/local/bin/python3.5
import asyncio
from aiohttp import ClientSession
sema = asyncio.BoundedSemaphore(5)
async def hello(url):
async with ClientSession() as session:
async with sema, session.get(url) as response:
response = await response.read()
print(response)
loop = asyncio.get_event_loop()
loop.run_until_complete(hello("http://httpbin.org/headers"))
Example taken from here. The page is also a good primer for asyncio and aiohttp in general.
OK, so this is really silly but I just replaces yield from with await in the semaphore context manager and it is working perfectly.
sema = asyncio.BoundedSemaphore(5)
async def get_page_text(url):
with (await sema):
try:
resp = await aiohttp.request('GET', url)
if resp.status == 200:
ret_val = await resp.text()
except:
raise ValueError
finally:
await resp.release()
return ret_val
For the semaphore only:
sem = asyncio.Semaphore(10)
# ... later
async with sem:
# work with shared resource
which is equivalent to:
sem = asyncio.Semaphore(10)
# ... later
await sem.acquire()
try:
# work with shared resource
finally:
sem.release()
ref:
https://docs.python.org/3/library/asyncio-sync.html#asyncio.Semaphore