Repository: encode/httpx

Issue:
httpx\_client.py", line 1991, in __del__ AttributeError: 'NoneType' object has no attribute 'OPENED'
The starting point for issues should usually be a discussion...

https://github.com/encode/httpx/discussions

Possible bugs may be raised as a "Potential Issue" discussion, feature requests may be raised as an "Ideas" discussion. We can then determine if the discussion needs to be escalated into an "Issue" or not.

This will help us ensure that the "Issues" list properly reflects ongoing or needed work on the project.

---

- [ ] Initially raised as discussion #...

Sender Runtime Finished ...
[<Response [200 OK]>, <Response [200 OK]>, <Response [200 OK]>, <Response [200 OK]>]
Exception ignored in: <function AsyncClient.__del__ at 0x000001C2BCC04A60>
Traceback (most recent call last):
  File "C:\ANACONNA\lib\site-packages\httpx\_client.py", line 1991, in __del__
AttributeError: 'NoneType' object has no attribute 'OPENED'

__ If I Delete The  \_\_del\_\_ function in _client.py , my code can work without error, but if not ,the error above will just happend..
And my function can get The coroutine data return , but I still don know why this error happend? 
Is Python garbage Recycle effect this ? __


And The  \_\_del\_\_  code is 

```
    def __del__(self) -> None:
        # We use 'getattr' here, to manage the case where '__del__()' is called
        # on a partially initiallized instance that raised an exception during
        # the call to '__init__()'.
        if getattr(self, "_state", None) == ClientState.OPENED:  # noqa: B009
            # Unlike the sync case, we cannot silently close the client when
            # it is garbage collected, because `.aclose()` is an async operation,
            # but `__del__` is not.
            #
            # For this reason we require explicit close management for
            # `AsyncClient`, and issue a warning on unclosed clients.
            #
            # The context managed style is usually preferable, because it neatly
            # ensures proper resource cleanup:
            #
            #     async with httpx.AsyncClient() as client:
            #         ...
            #
            # However, an explicit call to `aclose()` is also sufficient:
            #
            #    client = httpx.AsyncClient()
            #    try:
            #        ...
            #    finally:
            #        await client.aclose()
            warnings.warn(
                f"Unclosed {self!r}. "
                "See https://www.python-httpx.org/async/#opening-and-closing-clients "
                "for details."
            )


```


Discussion:

Resolving patch:
diff --git a/httpx/_client.py b/httpx/_client.py
--- a/httpx/_client.py
+++ b/httpx/_client.py
@@ -1273,13 +1273,6 @@ def __exit__(
             if transport is not None:
                 transport.__exit__(exc_type, exc_value, traceback)
 
-    def __del__(self) -> None:
-        # We use 'getattr' here, to manage the case where '__del__()' is called
-        # on a partially initiallized instance that raised an exception during
-        # the call to '__init__()'.
-        if getattr(self, "_state", None) == ClientState.OPENED:  # noqa: B009
-            self.close()
-
 
 class AsyncClient(BaseClient):
     """
@@ -1983,34 +1976,3 @@ async def __aexit__(
         for proxy in self._mounts.values():
             if proxy is not None:
                 await proxy.__aexit__(exc_type, exc_value, traceback)
-
-    def __del__(self) -> None:
-        # We use 'getattr' here, to manage the case where '__del__()' is called
-        # on a partially initiallized instance that raised an exception during
-        # the call to '__init__()'.
-        if getattr(self, "_state", None) == ClientState.OPENED:  # noqa: B009
-            # Unlike the sync case, we cannot silently close the client when
-            # it is garbage collected, because `.aclose()` is an async operation,
-            # but `__del__` is not.
-            #
-            # For this reason we require explicit close management for
-            # `AsyncClient`, and issue a warning on unclosed clients.
-            #
-            # The context managed style is usually preferable, because it neatly
-            # ensures proper resource cleanup:
-            #
-            #     async with httpx.AsyncClient() as client:
-            #         ...
-            #
-            # However, an explicit call to `aclose()` is also sufficient:
-            #
-            #    client = httpx.AsyncClient()
-            #    try:
-            #        ...
-            #    finally:
-            #        await client.aclose()
-            warnings.warn(
-                f"Unclosed {self!r}. "
-                "See https://www.python-httpx.org/async/#opening-and-closing-clients "
-                "for details."
-            )


Test patch:
diff --git a/tests/client/test_async_client.py b/tests/client/test_async_client.py
--- a/tests/client/test_async_client.py
+++ b/tests/client/test_async_client.py
@@ -286,14 +286,6 @@ async def test_client_closed_state_using_with_block():
         await client.get("http://example.com")
 
 
-@pytest.mark.usefixtures("async_environment")
-async def test_deleting_unclosed_async_client_causes_warning():
-    client = httpx.AsyncClient(transport=httpx.MockTransport(hello_world))
-    await client.get("http://example.com")
-    with pytest.warns(UserWarning):
-        del client
-
-
 def unmounted(request: httpx.Request) -> httpx.Response:
     data = {"app": "unmounted"}
     return httpx.Response(200, json=data)