classification
Title: Attribute error with flush on stdout,stderr
Type: behavior Stage:
Components: Documentation, IO Versions: Python 3.4, Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Jimbofbx, docs@python, jbmilam, martin.panter, pitrou, r.david.murray, serhiy.storchaka
Priority: normal Keywords:

Created on 2011-05-06 17:44 by Jimbofbx, last changed 2019-03-15 22:01 by BreamoreBoy.

Messages (8)
msg135347 - (view) Author: James Hutchison (Jimbofbx) Date: 2011-05-06 17:44
When upgrading from Python 3.1 to Python 3.2 I noticed that when my program closed it printed out a non-consequential AttributeError Exception. My program had a custom class that replaced stdout and stderr for use in a piped program (it flushed the buffer after every print statement)

I was able to reduce my code down to this simple test case that will reproduce the issue. Note that this doesn't show up in idle.

code:
import sys
from time import sleep
import subprocess

python31loc = r"C:\python31\python.exe";
python32loc = r"C:\python32\python.exe";
myname = "attributeError.py";

class FlushFile(object):
    #"""Write-only flushing wrapper for file-type objects."""
    def __init__(self, f):
        self.f = f
        try:
            self.encoding = f.encoding;
        except:
            pass;
    def write(self, x):
        self.f.write(x)
        self.f.flush()

# sets stdout and stderr to autoflush
def setAutoFlush():
    if sys.__stdout__ != None: # will be None in IDLE
        sys.stdout = FlushFile(sys.__stdout__);
        sys.stderr = FlushFile(sys.__stderr__);

if __name__ == "__main__":
    setAutoFlush();
    if(len(sys.argv) == 1):
        print("Testing python 3.1");
        output = subprocess.check_output("%s %s -output" % (python31loc, myname));
        print("Should see no error");
        print("Testing python 3.2");
        output = subprocess.check_output("%s %s -output" % (python32loc, myname));
        print("Should see no error");
        sleep(16);


Output:
Testing python 3.1
Should see no error
Testing python 3.2
Exception AttributeError: 'flush' in <__main__.FlushFile object at 0x00C347F0> i
gnored
Should see no error
msg135353 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-05-06 18:14
Hmm.  That error message is more than a bit misleading.  What you need to do is add a flush method to your FlushFile class.  Something changed between 3.1 and 3.2 that causes that message to be generated instead of suppressed.  Not sure what it was.  The surprising thing is that you only see it once...flush added to your class is called four times.

There is at least a bug in the message here.
msg135357 - (view) Author: James Hutchison (Jimbofbx) Date: 2011-05-06 18:28
You are right, when I add:

    def flush(self):
        pass;

the error goes away.

When I have this:

    def flush():
        pass;

I get:

Exception TypeError: 'flush() takes no arguments (1 given)' in <__main__.FlushFile object at 0x00C2AB70> ignored

This leads me to believe that sys.stdout.flush() is being called on program close

So this would be the correct implementation of my flushfile override:

class FlushFile(object):
    #"""Write-only flushing wrapper for file-type objects."""
    def __init__(self, f):
        self.f = f;
        self.flush = f.flush;
        try:
            self.encoding = f.encoding;
        except:
            pass;
    def write(self, x):
        self.f.write(x)
        self.f.flush()
msg223139 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2014-07-15 19:34
With 3.4.1 and similarly with 3.5.0a0 I get

Testing python 3.4
C:\python34\python.exe: can't open file 'attributeError.py': [Errno 2] No such file or directory
Traceback (most recent call last):
  File "C:\Users\Mark\MyPython\mytest.py", line 34, in <module>
    output = subprocess.check_output("%s %s -output" % (python34loc, myname));
  File "c:\python34\lib\subprocess.py", line 620, in check_output
    raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command 'C:\python34\python.exe attributeError.py -output' returned non-zero exit status 2
Exception ignored in: <__main__.FlushFile object at 0x015E3EB0>
AttributeError: 'FlushFile' object has no attribute 'flush'
msg229647 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2014-10-18 17:44
Since 29ba6c399090 stdout and stderr flush upon exit. But any errors on flushing were swallowed. Since 4ca497f4819c (issue5319) an error is printed if stdout flushing fails.

FlushFile doesn't provide all methods and attributes of io.TextIOBase. But it is not required that sys.stdout should be an instance of io.TextIOBase or provide the flush() method. I suppose this is either not a bug or documentation issue.
msg243633 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-05-19 22:52
The documentation already says that “stdout” and friends are meant to be text files, and that they may be replaced with file-like objects like StringIO. Perhaps the documentation could be more explicit about what text file API is required internally (either TextIOBase, or list the required subset of methods).
msg244616 - (view) Author: Brandon Milam (jbmilam) * Date: 2015-06-01 21:25
I've been looking over the issue and the error is just raised by the stdout change not the stderr change (when the stdout line is commented out in the setAutoFlush function no error is raised). The flush method doesn't seem to be required as Serhiy pointed out since the script still is able to run. This is the cause for the error, however and I think that the required subset of methods for stdout objects to avoid errors could be clarified in the documentation. This documentation addition I think would be best under the sys.stdout info rather than under io.TextIOBase since the error can be raised without going through this class at all like in the original post.

I would like to add this documentation under sys.stdout as required subset of methods that must be defined and was wondering if there were any other methods than flush() that would need to be defined.
msg244648 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-06-02 04:59
I wouldn’t expect to see a message for stderr because there is nowhere else to send the message. However with my patch for Issue 5319, at least we get a non-zero exit status.

Brandon: I agree this should be under sys.stdin/out/err; I wasn’t saying to put it under the io.TextIOBase documentation. What I meant was one option would be to refer to that class as a duck-typing API. Say something like: “sys.stdout [etc] may be replaced with other objects, as long as they implement [the write-only parts, etc of] the TextIOBase API [optionally ‘buffer’ etc]”. Exact details to be determined.
History
Date User Action Args
2019-03-15 22:01:57BreamoreBoysetnosy: - BreamoreBoy
2015-06-02 04:59:51martin.pantersetmessages: + msg244648
2015-06-01 21:25:14jbmilamsetnosy: + jbmilam
messages: + msg244616
2015-05-19 22:52:03martin.pantersetnosy: + martin.panter, docs@python
messages: + msg243633

assignee: docs@python
components: + Documentation
2014-10-18 17:44:51serhiy.storchakasetversions: + Python 3.4, Python 3.5, - Python 3.2
nosy: + serhiy.storchaka, pitrou

messages: + msg229647

components: - Windows
2014-07-15 19:34:44BreamoreBoysetnosy: + BreamoreBoy
messages: + msg223139
2011-05-06 18:28:05Jimbofbxsetmessages: + msg135357
2011-05-06 18:14:22r.david.murraysetnosy: + r.david.murray
messages: + msg135353
2011-05-06 17:44:37Jimbofbxcreate