You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow Responses to be used as Context Managers #393
I think this is a good thing beyond Requests compatibility — ensures that all resources are properly closed in case something goes wrong. I'm kind of growing the intuition that ideally we should be following trio's lessons and enforce (async) context manager usage everywhere — on clients, on responses, …
This is relevant only for the streaming case.
In other cases the response has been closed by the point it's returned from the function.
There's a question here to be had in that client.get(..., stream=True) is actually fundamentally different to client.get(...) because you really want to be using a context manager for the first case.
Requests has exactly the same issue, and actually makes it really easy to not close streaming responses. One option that we could do here that's a bit radical would be to diverge from the requests API here, even through stream=True is a fairly widely used case.
Eg. client.stream() could return a context managed response. (It might have a default method='get' that could be overidden.)
One other bugbear to be wary of here is that "stream" in this context specifically means "stream the response", not "stream the request" (which yes, we support, but that's different), but the naming isn't very clear about the expectation.
Main question here is where we want to go with the API...
Add a .stream(method='GET') method which is always what we use for streaming cases, so that we can ensure that they're always context-manged.
Stay in line with requests and just use stream=True on the existing methods. Keeps the API the same, but really easy to fail to close a response, which isn't awful but will leave the connection hanging.
$ python debug/client.pydebug/client.py:8: RuntimeWarning: coroutine 'get' was never awaited async with httpx.get(url) as resp:RuntimeWarning: Enable tracemalloc to get the object allocation tracebackTraceback (most recent call last): File "debug/client.py", line 12, in <module> asyncio.run(main()) File "/Users/florimond/.pyenv/versions/3.8.0/lib/python3.8/asyncio/runners.py", line 43, in run return loop.run_until_complete(main) File "/Users/florimond/.pyenv/versions/3.8.0/lib/python3.8/asyncio/base_events.py", line 608, in run_until_complete return future.result() File "debug/client.py", line 8, in main async with httpx.get(url) as resp:AttributeError: __aexit__
Activity
florimondmanca commentedon Sep 27, 2019
I think this is a good thing beyond Requests compatibility — ensures that all resources are properly closed in case something goes wrong. I'm kind of growing the intuition that ideally we should be following trio's lessons and enforce (async) context manager usage everywhere — on clients, on responses, …
lovelydinosaur commentedon Sep 27, 2019
Okay, so...
This is relevant only for the streaming case.
In other cases the response has been closed by the point it's returned from the function.
There's a question here to be had in that
client.get(..., stream=True)is actually fundamentally different toclient.get(...)because you really want to be using a context manager for the first case.Requests has exactly the same issue, and actually makes it really easy to not close streaming responses. One option that we could do here that's a bit radical would be to diverge from the
requestsAPI here, even throughstream=Trueis a fairly widely used case.Eg.
client.stream()could return a context managed response. (It might have a defaultmethod='get'that could be overidden.)One other bugbear to be wary of here is that "stream" in this context specifically means "stream the response", not "stream the request" (which yes, we support, but that's different), but the naming isn't very clear about the expectation.
gdhameeja commentedon Oct 3, 2019
I'd like to work on this.
lovelydinosaur commentedon Oct 4, 2019
Main question here is where we want to go with the API...
.stream(method='GET')method which is always what we use for streaming cases, so that we can ensure that they're always context-manged.requestsand just usestream=Trueon the existing methods. Keeps the API the same, but really easy to fail to close a response, which isn't awful but will leave the connection hanging.sethmlarson commentedon Oct 4, 2019
Maybe we can put a warning on the Responses garbage collector that it wasn't closed properly, similar to files?
lovelydinosaur commentedon Nov 27, 2019
Closing this. Evidentally outdated somewhere along the line - we do support responses as context managers. 👍
florimondmanca commentedon Nov 29, 2019
@tomchristie Do we? The
Responseclass doesn't implement__aenter__()/__aexit__(), so this might have been an oversight?lovelydinosaur commentedon Dec 9, 2019
Obsoleted by #600