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
asyncio: ConnectionResetError after StreamWriter is garbage collected #109321
Traceback (most recent call last):
File "/home/rigens/aio_test1.py", line 50, in <module>
asyncio.run(fetch())
File "/usr/local/miniconda/envs/py311_5/lib/python3.11/asyncio/runners.py", line 190, in runreturn runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/miniconda/envs/py311_5/lib/python3.11/asyncio/runners.py", line 118, in runreturnself._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/miniconda/envs/py311_5/lib/python3.11/asyncio/base_events.py", line 653, in run_until_completereturn future.result()
^^^^^^^^^^^^^^^
File "/home/rigens/aio_test1.py", line 41, in fetchawait writer.drain()
File "/usr/local/miniconda/envs/py311_5/lib/python3.11/asyncio/streams.py", line 378, in drainawaitself._protocol._drain_helper()
File "/usr/local/miniconda/envs/py311_5/lib/python3.11/asyncio/streams.py", line 167, in _drain_helperraiseConnectionResetError('Connection lost')
ConnectionResetError: Connection lost
It is not recommended to manually instantiate StreamWriter 1, StreamReader...
It's not about manually instantiating the StreamWriter....
The code above is given only as an example
If you want to just use the transport then you should loop.create_connection API and not streaming APIs.
I want to reuse the transport received from some third-party component that uses the streams api (StreamReader, StreamWriter) to communicate with the remote host.
This approach worked fine until version 3.11.5 and this PR #107656
What was the purpose of closing the transport in the StreamWriter __del__ method, why not do it in the __del__ method of the transport itself?
The current asyncio API provides no way to attach StreamReader and StreamWriter to a transport other than UNIX sockets and TCP. I'm trying use a line-based API with a SerialTransport (wrapping a serial port).
#107656 unexpectedly closing the transport on __del__ breaks instances where set_protocol was used:
# Transport is already opentransport= ...
loop=asyncio.get_running_loop()
reader=asyncio.StreamReader(limit=65536, loop=loop)
protocol=asyncio.StreamReaderProtocol(reader, loop=loop)
writer=asyncio.StreamWriter(transport, protocol, reader, loop)
transport.set_protocol(protocol)
# Do line-based operations using `reader` and `writer`
...
# Change protocolstransport.set_protocol(new_protocol)
There is no way to detach the transport without digging into _transport and providing it a mock transport to "close":
It would be nice to have an API to clear writer._transport without closing.
If that's your main point, could you open a new issue please? While I'm not sure that this issue should remain closed, I don't think it's the place to discuss new feature requests.
What was the purpose of closing the transport in the StreamWriter __del__ method, why not do it in the __del__ method of the transport itself?
AFAICT the reason is because the transport is not under our control -- there are many possible transports and we don't want to add a __del__ method to all of them.
FWIW: The asyncio streams implementation is not very flexible. There are a variety of design aspects that we wish we had done differently. But it's about a decade too late. We've contemplated deprecating it, but didn't have the energy to design and implement something better to replace it. But it looks like you are trying to do something unusual with it, and it's just hard to support that. The changes that broke your code, after all, were put in place to fix someone else's code. Alas.
Activity
kumaraditya303 commentedon Sep 12, 2023
It is not recommended to manually instantiate
StreamWriter1,StreamReader2 objects and transports, so this is not a bug ofasyncio.Footnotes
https://docs.python.org/3/library/asyncio-stream.html#asyncio.StreamWriter ↩
https://docs.python.org/3/library/asyncio-stream.html#asyncio.StreamReader ↩
kumaraditya303 commentedon Sep 12, 2023
If you want to just use the transport then you should
loop.create_connectionAPI and not streaming APIs.rigens commentedon Sep 13, 2023
It's not about manually instantiating the StreamWriter....
The code above is given only as an example
I want to reuse the transport received from some third-party component that uses the streams api (StreamReader, StreamWriter) to communicate with the remote host.
This approach worked fine until version 3.11.5 and this PR #107656
What was the purpose of closing the transport in the StreamWriter
__del__method, why not do it in the__del__method of the transport itself?This PR has already broken some libraries: romis2012/aiohttp-socks#27 (comment)
The mentioned PR at least breaks backward compatibility
rigens commentedon Sep 13, 2023
@kumaraditya303, if you don't have any arguments, please reopen the issue.
build: update pinned aiohttp-socks (partial rerun freeze_packages)
puddly commentedon Jan 3, 2024
The current asyncio API provides no way to attach
StreamReaderandStreamWriterto a transport other than UNIX sockets and TCP. I'm trying use a line-based API with aSerialTransport(wrapping a serial port).#107656 unexpectedly closing the transport on
__del__breaks instances whereset_protocolwas used:There is no way to detach the transport without digging into
_transportand providing it a mock transport to "close":It would be nice to have an API to clear
writer._transportwithout closing.gvanrossum commentedon Jan 3, 2024
@puddly
If that's your main point, could you open a new issue please? While I'm not sure that this issue should remain closed, I don't think it's the place to discuss new feature requests.
gvanrossum commentedon Jan 3, 2024
@rigens
The
__del__method got some improvements in #109538.Is it still preventing you to do what you want to?
gvanrossum commentedon Jan 4, 2024
@rigens
AFAICT the reason is because the transport is not under our control -- there are many possible transports and we don't want to add a
__del__method to all of them.FWIW: The asyncio streams implementation is not very flexible. There are a variety of design aspects that we wish we had done differently. But it's about a decade too late. We've contemplated deprecating it, but didn't have the energy to design and implement something better to replace it. But it looks like you are trying to do something unusual with it, and it's just hard to support that. The changes that broke your code, after all, were put in place to fix someone else's code. Alas.
build: update pinned aiohttp-socks (partial rerun freeze_packages)