Here is a minimal reproducer:
import asyncio
async def supervisor():
async with asyncio.TaskGroup() as tg:
for _ in range(20):
tg.create_task(send())
async def send():
_, writer = await asyncio.open_connection("localhost", 8888)
writer.write(b"test")
await writer.drain()
if __name__ == "__main__":
asyncio.run(supervisor())
This results in:
+ Exception Group Traceback (most recent call last):
| File "/tmp/repro.py", line 17, in <module>
| asyncio.run(supervisor())
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 190, in run
| return runner.run(main)
| ^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 118, in run
| return self._loop.run_until_complete(task)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
| return future.result()
| ^^^^^^^^^^^^^^^
| File "/tmp/repro.py", line 5, in supervisor
| async with asyncio.TaskGroup() as tg:
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/taskgroups.py", line 145, in __aexit__
| raise me from None
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/tmp/repro.py", line 11, in send
| _, writer = await asyncio.open_connection("localhost", 8888)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/streams.py", line 48, in open_connection
| transport, _ = await loop.create_connection(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 1113, in create_connection
| transport, protocol = await self._create_connection_transport(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 1143, in _create_connection_transport
| transport = self._make_socket_transport(sock, protocol, waiter)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/selector_events.py", line 61, in _make_socket_transport
| return _SelectorSocketTransport(self, sock, protocol, waiter,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/selector_events.py", line 936, in __init__
| base_events._set_nodelay(self._sock)
| File "/opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 196, in _set_nodelay
| sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
| OSError: [Errno 22] Invalid argument
+------------------------------------
on both Linux and Mac. If I only create a single task, then it succeeds every time. Am I misunderstanding what the StreamWriter
object is? My intention here is to create multiple TCP client connections using asyncio.