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
Hello,
I'm using httpx as Async but i'm having issues with connections never being closed and reaching the socket limit on my server.
I can see that both the async client and the request have a close() method. However, I cannot understand what they're supposed to do, or well - which one I'm supposed to use.
Would it be possible to have more clearer documentation on this?.
Switching to the context manager syntax will close all remaining keep-alive connections on exit:
asyncwithhttpx.AsyncClient() asclient:
response=awaitclient.get(...)
# All connections are now closed.# You can still safely access the read response content outside the context block, e.g.:html=response.text
If you're using stream=True then you need to make sure to .close() the response at some point, as documented here. We have an open issue to close pending streaming responses on exit too (#35) which would allow users not to worry about manually closing the response.
Does this help? Feel free to share some code if you'd like help on some more specific items.
Oh so the AsyncClient has a context manager syntax...
I'm gonna try switching to that, to see if I keep leaking connections. Additionally, consider i have a list like this:
To my understanding it would do something like this: …
I think you're correct. A keep-alive connection to one site isn't dropped when you request another one (that's actually the purpose of the internal connection pool).
About the retry extension, the .get() method is one level of abstraction above the connection pool, so connections should all be automatically managed and cleaned up as usual. (A note on the code: you should probably be using self.log instead of AsyncClient.log and super().get() instead of httpx.AsyncClient.get().)
I guess your approach works but it shows the necessity of providing a clean extension mechanism for Client/AsyncClient. :-) (Actually, we have an internal middleware mechanism to handle this kind of use case, but it's not public yet, i.e. there's no way that add another middleware to the client from the outside yet. You can take a look at #295 for discussions.)
@edocod1 It turns out I was wrong about the necessity of calling response.read(). Actually, you only need to do so if you're using response streaming, e.g. await client.get(..., stream=True). I'll update my comment with a fix.
Activity
florimondmanca commentedon Sep 14, 2019
Hi @edocod1,
I'm assuming you are invoking the client as shown in the docs, i.e.:
Switching to the context manager syntax will close all remaining keep-alive connections on exit:
If you're using
stream=Truethen you need to make sure to.close()the response at some point, as documented here. We have an open issue to close pending streaming responses on exit too (#35) which would allow users not to worry about manually closing the response.Does this help? Feel free to share some code if you'd like help on some more specific items.
edocod1 commentedon Sep 15, 2019
Oh so the AsyncClient has a context manager syntax...
I'm gonna try switching to that, to see if I keep leaking connections. Additionally, consider i have a list like this:
links = ['//site.com/hello.jpg', '//site.com/bye.jpg', '//different.yes/another.jpg', '//site.com/ofcourse.jpg, '//site.com/yes.jpg']and i ran it in a loop:
To my understanding it would do something like this:
withblock)Right? Or would the connection to different.yes drop the one on site.com?
Additionally, I've extended the AsyncClient class to retry in case of failure:
Would this mess with the connection closing mechanism?
florimondmanca commentedon Sep 15, 2019
I think you're correct. A keep-alive connection to one site isn't dropped when you request another one (that's actually the purpose of the internal connection pool).
About the retry extension, the
.get()method is one level of abstraction above the connection pool, so connections should all be automatically managed and cleaned up as usual. (A note on the code: you should probably be usingself.loginstead ofAsyncClient.logandsuper().get()instead ofhttpx.AsyncClient.get().)I guess your approach works but it shows the necessity of providing a clean extension mechanism for
Client/AsyncClient. :-) (Actually, we have an internal middleware mechanism to handle this kind of use case, but it's not public yet, i.e. there's no way that add another middleware to the client from the outside yet. You can take a look at #295 for discussions.)florimondmanca commentedon Sep 15, 2019
@edocod1 It turns out I was wrong about the necessity of calling
response.read(). Actually, you only need to do so if you're using response streaming, e.g.await client.get(..., stream=True). I'll update my comment with a fix.florimondmanca commentedon Sep 15, 2019
@edocod1 Feel free to take a look at and comment on #344 which proposes a documentation update. :)
edocod1 commentedon Sep 15, 2019
Thank you very much for the help and suggestions! I was able to fix it.
Have a nice day