Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows - Python 3.8+ raises "RuntimeError: Event Loop is closed" on exit. #914

Open
rmawatson opened this issue Apr 30, 2020 · 42 comments
Open
Labels
bug Something isn't working concurrency/asyncio Issues related to concurrency (asyncio-only) external Root cause pending resolution in an external dependency

Comments

@rmawatson
Copy link

rmawatson commented Apr 30, 2020

Checklist

  • [ x] The bug is reproducible against the latest release and/or master.
  • [ x] There are no similar issues or pull requests to fix it yet.

Describe the bug

I get the following traceback when running the attached code

404
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000017C63D5E310>
Traceback (most recent call last):
  File "C:\Python\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "C:\Python\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 715, in call_soon
    self._check_closed()
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

To reproduce

async def testing():
    client = httpx.AsyncClient()
    response = await client.get("https://www.google.com/")
    await client.aclose()
    print(response.status_code)

async def main():
   await testing()

asyncio.run(main())

Inserting time.sleep(0.1) at the end of main() fixes it. Possibly due to the same reasons in the issues linked below.

Environment

  • Windows 10 64bit
  • Python version: 3.8.1
  • HTTPX version 0.12.1

Possibly the same as this and this

@florimondmanca
Copy link
Member

I assume this is yet another strange issue with asyncio’s stream.close() - it schedules the closing of the socket but it’s not guaranteed to be done once client.aclose finishes, which means the socket is actually deleted upon garbage collection, and by then I suppose the event loop is already closed... The sleep() call fixed this because it allows asyncio to execute the close callback before proceeding to shutdown the async environment.

See also #825 for more discussion on a possibly related issue.

Have you tried running this on Python 3.8.2?

@florimondmanca florimondmanca added bug Something isn't working concurrency/asyncio Issues related to concurrency (asyncio-only) labels Apr 30, 2020
@tomchristie
Copy link
Member

Also: May well be specific to Window's Proactor event loop.

@florimondmanca
Copy link
Member

Yes, definitely looks like a Windows specific issue to me - the linked issues are for Windows too.

@rmawatson
Copy link
Author

@florimondmanca , yes upgraded to 3.8.2 to check, the result is the same.

@Baysul
Copy link

Baysul commented May 1, 2020

Can confirm this is an issue with the latest PyPi version of aiohttp and Python 3.8.2 on Windows.

@florimondmanca
Copy link
Member

Okay, thank you.

I personally don’t have a Windows machine so help with investigation and possible fixes would help.

Would we need to consider black magic such as aio-libs/aiohttp#1925 (comment)? How about aio-libs/aiohttp#3733?

FYI this is likely to be something to address on the HTTPCore side, as connection management and networking is done there. Might then be helpful to first come up with a minimal repro example using HTTPCore only?

@tomchristie
Copy link
Member

It'd also be helpful to try switching to using SelectorEventLoop and let us know what the behaviour is like then... https://docs.python.org/3/library/asyncio-eventloop.html#event-loop-implementations (Or to try with Python 3.7 or earlier)

Python only switched the default event loop to proactor from 3.8 onwards. https://docs.python.org/3/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy

@euri10
Copy link
Member

euri10 commented May 1, 2020 via email

@Baysul
Copy link

Baysul commented May 1, 2020

The workaround is to use the selector event loop like this:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

The following from the documentation will not resolve this issue (for some reason):

import asyncio
import selectors

selector = selectors.SelectSelector()
loop = asyncio.SelectorEventLoop(selector)
asyncio.set_event_loop(loop)

@rmawatson
Copy link
Author

Thanks @Baysul.

This bug report looks like it is tracking the same issue.

@tomchristie
Copy link
Member

Same as with #825 - Haven't looked into how awkward it is to do, but really I think we'd want to monkeypatch asyncio's socket unwrapping behaviour, so that we can reliably call .wait_closed(...) without it potentially hanging.

@tomchristie
Copy link
Member

tomchristie commented Aug 20, 2020

Can anyone on Windows, running Python 3.8+ confirm what currently happens when running this?...

import httpx
import asyncio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://login.microsoftonline.com/")
        print(r)

asyncio.run(main(), debug=True)

Trying to verify if we're still exposed to this issue. (I guess we are but 🤷‍♂️)

@tomchristie tomchristie changed the title RuntimeError: Event Loop is closed Windows - Python 3.8+ raises "RuntimeError: Event Loop is closed" on exit. Aug 20, 2020
@dalf
Copy link

dalf commented Aug 20, 2020

Using:

  • Windows 10 64bit
  • Python 3.8.5
  • httpx 0.14.1

I have a httpx._exceptions.ConnectTimeout even with timeout=60 or http2=True.

@tomchristie
Copy link
Member

tomchristie commented Aug 20, 2020

@dalf - Thanks!

Also uh... that's not at all what I was expecting / looking for. 🙃🙃🙃

Does that replicate on other URLs?...

  • "https://www.google.com/"
  • "https://www.example.org/"

Does removing the debug=True change anything?

Does it work okay in the sync version?...

import httpx

def main():
   with httpx.Client() as client:
        r = client.get("https://login.microsoftonline.com/")
        print(r)

main()

Or with trio?... (Use pip install trio)

import httpx
import trio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://login.microsoftonline.com/")
        print(r)

trio.run(main)

@dalf
Copy link

dalf commented Aug 20, 2020

Maybe my report is irrelevant, I'm not familiar with the Python Windows environment:

import httpx
import requests

r_requests = requests.get('https://www.google.com')
r_httpx = httpx.get('https://www.google.com')

@tomchristie
Copy link
Member

🤨

That's pretty relevant. But just super surprising.

Are you able to double double check you've got fully up to date httpx and httpcore versions installed?
Is anyone else able to confirm?

@dalf
Copy link

dalf commented Aug 20, 2020

To do the test, I've installed Python from https://www.python.org/ftp/python/3.8.5/python-3.8.5.exe (it wasn't installed before), and just pip install httpx[http2]

pip freeze shows

httpcore==0.10.2
httpx==0.14.1

I think a test from someone else would be helpful.

@j178
Copy link
Member

j178 commented Aug 20, 2020

I ran some tests:

Test against https://github.com/

Sync client works fine:

import httpx
import requests

resp = httpx.get('https://github.com/')
print('httpx', resp)

resp = requests.get('https://github.com/')
print('requests', resp)

results:

httpx <Response [200 OK]>
requests <Response [200]>

Async client, run with asyncio,

import httpx
import asyncio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://github.com/")
        print(r)

asyncio.run(main(), debug=True)

results:

<Response [200 OK]>
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000024774DEA0D0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Async client, run with trio, works fine:

import httpx
import trio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://github.com/")
        print(r)

trio.run(main)

results:

<Response [200 OK]>

Test against https://login.microsoftonline.com/

Run with sync client

import httpx
import requests

resp = httpx.get('https://login.microsoftonline.com/')
print('httpx', resp)

resp = requests.get('https://login.microsoftonline.com/')
print('requests', resp)

results:

requests always succeed, httpx *sometimes* failed with `ConnectTimeout`
requests <Response [200]>
Traceback (most recent call last):
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 342, in map_exceptions
    yield
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 798, in _send_single_request
    ) = transport.request(
  File "e:\projects\pycharm\httpcore\httpcore\_sync\connection_pool.py", line 188, in request
    response = connection.request(
  File "e:\projects\pycharm\httpcore\httpcore\_sync\connection.py", line 83, in request
    self.socket = self._open_socket(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_sync\connection.py", line 104, in _open_socket
    return self.backend.open_tcp_stream(
  File "e:\projects\pycharm\httpcore\httpcore\_backends\sync.py", line 144, in open_tcp_stream
    return SyncSocketStream(sock=sock)
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpcore\httpcore\_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.ConnectTimeout: _ssl.c:1106: The handshake operation timed out

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".\sync.py", line 12, in <module>
    resp = httpx.get(url)
  File "e:\projects\pycharm\httpx\httpx\_api.py", line 174, in get
    return request(
  File "e:\projects\pycharm\httpx\httpx\_api.py", line 89, in request
    return client.request(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 673, in request
    return self.send(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 703, in send
    response = self._send_handling_redirects(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 732, in _send_handling_redirects
    response = self._send_handling_auth(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 769, in _send_handling_auth
    response = self._send_single_request(request, timeout)
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 792, in _send_single_request
    (
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 359, in map_exceptions
    raise mapped_exc(message, **kwargs) from exc  # type: ignore
httpx.ConnectTimeout: _ssl.c:1106: The handshake operation timed out

Running with asyncio

import httpx
import asyncio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://login.microsoftonline.com/")
        print(r)

asyncio.run(main(), debug=True)

results in three different types error(in an abritary way):

Error 1: Request succeed but with RuntimeError
<Response [200 OK]>
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001AB2649A0D0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001AB2649A0D0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Error 2: ConnectTimeout
Traceback (most recent call last):
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 342, in map_exceptions
    yield
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1402, in _send_single_request
    ) = await transport.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection_pool.py", line 188, in request
    response = await connection.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 83, in request
    self.socket = await self._open_socket(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 104, in _open_socket
    return await self.backend.open_tcp_stream(
  File "e:\projects\pycharm\httpcore\httpcore\_backends\auto.py", line 40, in open_tcp_stream
    return await self.backend.open_tcp_stream(
  File "e:\projects\pycharm\httpcore\httpcore\_backends\asyncio.py", line 240, in open_tcp_stream
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpcore\httpcore\_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.ConnectTimeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".\async_test.py", line 13, in <module>
    asyncio.run(main(), debug=True)
  File "D:\Programs\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File ".\async_test.py", line 10, in main
    r = await client.get("https://login.microsoftonline.com/")
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1441, in get
    return await self.request(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1274, in request
    response = await self.send(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1305, in send
    response = await self._send_handling_redirects(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1334, in _send_handling_redirects
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1371, in _send_handling_auth
    response = await self._send_single_request(request, timeout)
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1396, in _send_single_request
    (
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 359, in map_exceptions
    raise mapped_exc(message, **kwargs) from exc  # type: ignore
httpx.ConnectTimeout
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001E4DAFBA0D0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 108, in close
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
RuntimeError: Event loop is closed
Error 3: ReadTimeout
Traceback (most recent call last):
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 342, in map_exceptions
    yield
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1402, in _send_single_request
    ) = await transport.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection_pool.py", line 188, in request
    response = await connection.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 96, in request
    return await self.connection.request(method, url, headers, stream, timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 73, in request
    ) = await self._receive_response(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 130, in _receive_response
    event = await self._receive_event(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 160, in _receive_event
    data = await self.socket.read(self.READ_NUM_BYTES, timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_backends\asyncio.py", line 134, in read
    return await asyncio.wait_for(
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpcore\httpcore\_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.ReadTimeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".\async_test.py", line 13, in <module>
    asyncio.run(main(), debug=True)
  File "D:\Programs\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File ".\async_test.py", line 10, in main
    r = await client.get("https://login.microsoftonline.com/")
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1441, in get
    return await self.request(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1274, in request
    response = await self.send(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1305, in send
    response = await self._send_handling_redirects(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1334, in _send_handling_redirects
    response = await self._send_handling_auth(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1371, in _send_handling_auth
    response = await self._send_single_request(request, timeout)
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1396, in _send_single_request
    (
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 359, in map_exceptions
    raise mapped_exc(message, **kwargs) from exc  # type: ignore
httpx.ReadTimeout
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x00000222F9D43310>
transport: <_ProactorSocketTransport fd=372 read=<_OverlappedFuture cancelled created at D:\Programs\Python38\lib\asyncio\windows_events.py:461>>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 685, in _process_write_backlog
    self._transport.write(chunk)
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 359, in write
    self._loop_writing(data=bytes(data))
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 395, in _loop_writing
    self._write_fut = self._loop._proactor.send(self._sock, data)
AttributeError: 'NoneType' object has no attribute 'send'
Exception ignored in: <function _SSLProtocolTransport.__del__ at 0x00000222F9D02DC0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 322, in __del__
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 317, in close
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 594, in _start_shutdown
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 599, in _write_appdata
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 707, in _process_write_backlog
  File "D:\Programs\Python38\lib\asyncio\sslproto.py", line 721, in _fatal_error
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 151, in _force_close
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x00000222F9D6A0D0>
Traceback (most recent call last):
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
  File "D:\Programs\Python38\lib\asyncio\proactor_events.py", line 108, in close
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 719, in call_soon
  File "D:\Programs\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
RuntimeError: Event loop is closed

Run with trio

Sometimes succeed, sometimes failed with `ReadTimeout` or `ConnectTimeout`

ReadTimeout:

Traceback (most recent call last):
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 342, in map_exceptions
    yield
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1402, in _send_single_request
    ) = await transport.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection_pool.py", line 188, in request
    response = await connection.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 96, in request
    return await self.connection.request(method, url, headers, stream, timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 73, in request
    ) = await self._receive_response(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 130, in _receive_response
    event = await self._receive_event(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\http11.py", line 160, in _receive_event
    data = await self.socket.read(self.READ_NUM_BYTES, timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_backends\trio.py", line 63, in read
    return await self.stream.receive_some(max_bytes=n)
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpcore\httpcore\_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.ReadTimeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".\async_test-trio.py", line 12, in <module>
    trio.run(main)
  File "D:\Programs\Python38\lib\site-packages\trio\_core\_run.py", line 1896, in run
    raise runner.main_task_outcome.error
  File ".\async_test-trio.py", line 9, in main
    r = await client.get("https://login.microsoftonline.com/")
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1441, in get
    return await self.request(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1274, in request
    response = await self.send(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1305, in send
    response = await self._send_handling_redirects(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1334, in _send_handling_redirects
    response = await self._send_handling_auth(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1371, in _send_handling_auth
    response = await self._send_single_request(request, timeout)
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1396, in _send_single_request
    (
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 359, in map_exceptions
    raise mapped_exc(message, **kwargs) from exc  # type: ignore
httpx.ReadTimeout

ConnectTimeout:

Traceback (most recent call last):
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 342, in map_exceptions
    yield
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1402, in _send_single_request
    ) = await transport.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection_pool.py", line 188, in request
    response = await connection.request(
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 83, in request
    self.socket = await self._open_socket(timeout)
  File "e:\projects\pycharm\httpcore\httpcore\_async\connection.py", line 104, in _open_socket
    return await self.backend.open_tcp_stream(
  File "e:\projects\pycharm\httpcore\httpcore\_backends\auto.py", line 40, in open_tcp_stream
    return await self.backend.open_tcp_stream(
  File "e:\projects\pycharm\httpcore\httpcore\_backends\trio.py", line 168, in open_tcp_stream
    return SocketStream(stream=stream)
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpcore\httpcore\_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.ConnectTimeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".\async_test-trio.py", line 12, in <module>
    trio.run(main)
  File "D:\Programs\Python38\lib\site-packages\trio\_core\_run.py", line 1896, in run
    raise runner.main_task_outcome.error
  File ".\async_test-trio.py", line 9, in main
    r = await client.get("https://login.microsoftonline.com/")
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1441, in get
    return await self.request(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1274, in request
    response = await self.send(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1305, in send
    response = await self._send_handling_redirects(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1334, in _send_handling_redirects
    response = await self._send_handling_auth(
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1371, in _send_handling_auth
    response = await self._send_single_request(request, timeout)
  File "e:\projects\pycharm\httpx\httpx\_client.py", line 1396, in _send_single_request
    (
  File "D:\Programs\Python38\lib\contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "e:\projects\pycharm\httpx\httpx\_exceptions.py", line 359, in map_exceptions
    raise mapped_exc(message, **kwargs) from exc  # type: ignore
httpx.ConnectTimeout

Using:

  • Windows 10 64bit
  • Python 3.8.5
  • httpx latest master branch
  • httpcore latest master branch

@pprovart
Copy link

Windows 10
Python 3.10.2
NOTE: Problem occured before and after i installed httpx and httpcore
httpcore 0.14.7
httpx 0.22.0

Code gets the required data from BSCSCAN and then i get the Runtime Error.
The time.sleep(1) command didnt work.

PYTHON
import asyncio
from bscscan import BscScan

YOUR_API_KEY = "REDACTED"
CON_ADDR = "0xa38898a4ae982cb0131104a6746f77fa0da57aaa"
WAL_ADDR = "0x411709fd0cdd5f06ff6ef45b48aa0cb9842f01fc"

async def main():
async with BscScan(YOUR_API_KEY) as bsc:
print(await bsc.get_bnb_balance(address="0xa38898a4ae982cb0131104a6746f77fa0da57aaa")

if name == "main":
asyncio.run(main())

OUTPUT
image

@aabmets
Copy link

aabmets commented Feb 24, 2022

I'm having the same issue on Windows 10. It does not matter what library I'm using.
If the loop is an ProactorEventLoop, then it is guaranteed that it will cause an exception if
there have been any network requests made which use SSL or sessions.

@tomchristie tomchristie reopened this Feb 25, 2022
@tomchristie
Copy link
Member

tomchristie commented Feb 25, 2022

Okay - could you show me that absolute simplest possible example that reproduces this.

@pprovart's example here is pretty good - does it still replicate if you simplify it even further?...

import asyncio
import httpx

async def main():
    async with httpx.Client() as client:
        r = await client.get("https://www.example.com")
        print(r)

if name == "main":
    asyncio.run(main())

Also, does it replicate with both http and https URLs?

@Mennaruuk
Copy link

Nope, it works pretty well for me. I get <Response [301 Moved Permanently]> with and without HTTPS. I looked at this proposed solution, and I modified it as the following. It worked for me, not sure if it works for others. but I stopped getting the RuntimeError:

import platform

if platform.system() == 'Windows':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

@tomchristie
Copy link
Member

@Mennaruuk - Ah yup. Just looked though this thread and reminded myself of the comment here.

This is a bug in Python's stdlib with Windows. See: https://bugs.python.org/issue39232

One option here might be to check if the ProactorEventLoop is the default, and warn if it is.

@graingert
Copy link
Member

when using async with httpx.AsyncClient() as client the transport should be closed correctly by anyio and not trigger the __del__ so this looks like an anyio bug

@tomchristie
Copy link
Member

This bug in the Python stdlib appears to have been fixed now in 3.11 (and possibly backported to 3.10?)

python/cpython#83413

Are any windows users here able to attempt replicating the original issue on the latest patch versions of Python 3.9, 3.10 and 3.12?

@mbwmbw1337
Copy link

This bug in the Python stdlib appears to have been fixed now in 3.11 (and possibly backported to 3.10?)

python/cpython#83413

Are any windows users here able to attempt replicating the original issue on the latest patch versions of Python 3.9, 3.10 and 3.12?

I can test later today.

@FANGOD
Copy link

FANGOD commented Jan 18, 2023

This problem also occurs on linux.

Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x7f85c758ce50>
Traceback (most recent call last):
  File "/usr/lib/python3.8/asyncio/base_subprocess.py", line 126, in __del__
    self.close()
  File "/usr/lib/python3.8/asyncio/base_subprocess.py", line 104, in close
    proto.pipe.close()
  File "/usr/lib/python3.8/asyncio/unix_events.py", line 536, in close
    self._close(None)
  File "/usr/lib/python3.8/asyncio/unix_events.py", line 560, in _close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 711, in call_soon
    self._check_closed()
  File "/usr/lib/python3.8/asyncio/base_events.py", line 504, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

@kpostekk
Copy link

kpostekk commented Jan 18, 2023

This problem also occurs on linux.

Have you considered switching to recent version of python?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working concurrency/asyncio Issues related to concurrency (asyncio-only) external Root cause pending resolution in an external dependency
Projects
None yet
Development

No branches or pull requests