classification
Title: Allow setting line_buffering on existing TextIOWrapper
Type: enhancement Stage: resolved
Components: IO Versions: Python 3.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, ncoghlan, pitrou, serhiy.storchaka, stutzbach
Priority: normal Keywords:

Created on 2017-05-31 16:15 by pitrou, last changed 2017-06-03 15:48 by pitrou. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 1887 closed pitrou, 2017-05-31 16:47
PR 1922 merged pitrou, 2017-06-02 18:03
Messages (8)
msg294850 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-05-31 16:15
Currently, if you want to change the line buffering behaviour of standard streams, you can create a new stream and assign it to sys.{stdout,stderr,stdin}.  Unfortunately, it is common for references to the old streams to be stored in various places (such as logging configuration, or third-party libraries).  Replacing them all is probably a hopeless cause.  It would be much better if one could simply write `sys.stdout.line_buffering = True` and be done with it.
msg294922 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-06-01 09:38
This looks similar to issue15216 and may be merged with it. At least setting line_buffering and encoding should have unified interface. I see two possibilities of making this Pythonic:

* Make attributes writeable.

* Add a method (configure(), reopen(), or like) that takes new values as keyword arguments. This allows to change several attributes at a time.
msg294925 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-06-01 09:50
I don't think those two issues need to be merged.  Setting line_buffering and write_through is almost trivial, while setting the encoding seems to take a significant amount of effort.

That said, I agree that a unified interface may be nice.  Perhaps a reconfigure(**kwargs) method?
msg294931 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-06-01 10:41
First at all, I'm not sure that allowing to modify TextIOWrapper settings after creation is a good idea. I would be feeling uncomfortable if the third-party library changed the buffering or encoding settings of passed text stream for its own needs, and this stream is sys.stdout. For example set f.line_buffering = False for performance and break your logging. Creating a new TextIOWrapper for own needs looks safer. But changing the global state is the essential part of Nick's and your issues.

This could have long-term consequences, so it is worth to discuss the principle on the Python-Dev mailing list before applying the changes.
msg294933 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-06-01 10:43
Le 01/06/2017 à 12:41, Serhiy Storchaka a écrit :
> 
> First at all, I'm not sure that allowing to modify TextIOWrapper settings after creation is a good idea. I would be feeling uncomfortable if the third-party library changed the buffering or encoding settings of passed text stream for its own needs, and this stream is sys.stdout.

Agreed that third-party libraries should not, but we're talking about
applications here.

> For example set f.line_buffering = False for performance and break your logging. Creating a new TextIOWrapper for own needs looks safer.

Now you may have two TextIOWrappers alive wrapping the same buffered IO
object.
msg295016 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2017-06-02 13:25
Right, the request/requirement for in-place configuration changes arise from the fact the underlying buffer objects can't readily be shared, while makes swapping out the wrapper problematic if others may already have references to the original.

The "Don't do this implicitly in a library" admonition is then really the same one that applies to any unusual tinkering with global state (e.g. monkeypatching): you can definitely break things if you do it carelessly, so let the main application decide if and when global state updates are appropriate.


I do like "reconfigure()" as the API name, since that's then nicely amenable to expanding to all the settings supported by `open()` as concrete use cases arise. One thing we'll need to watch out for is the difference between "Leave this setting alone" and "Revert this setting to the global default".
msg295017 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-06-02 13:27
Thanks. I'll produce an updated PR using reconfigure() for line_buffering and write_through.
msg295074 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-06-03 10:32
New changeset 3c2817b6884a5fcf792197203f3c26b157210607 by Antoine Pitrou in branch 'master':
Fix bpo-30526: Add TextIOWrapper.reconfigure() and a TextIOWrapper.write_through attribute (#1922)
https://github.com/python/cpython/commit/3c2817b6884a5fcf792197203f3c26b157210607
History
Date User Action Args
2017-06-03 15:48:47pitrousetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2017-06-03 10:32:30pitrousetmessages: + msg295074
2017-06-02 18:03:23pitrousetpull_requests: + pull_request2002
2017-06-02 13:27:36pitrousetmessages: + msg295017
2017-06-02 13:25:58ncoghlansetmessages: + msg295016
2017-06-01 10:43:08pitrousetmessages: + msg294933
2017-06-01 10:41:30serhiy.storchakasetmessages: + msg294931
2017-06-01 09:50:32pitrousetstage: patch review
2017-06-01 09:50:27pitrousetmessages: + msg294925
2017-06-01 09:38:15serhiy.storchakasetnosy: + serhiy.storchaka, ncoghlan
messages: + msg294922
2017-05-31 16:47:51pitrousetpull_requests: + pull_request1965
2017-05-31 16:15:46pitroucreate