Python subclassing file types

I was hoping to write a simple tee class by subclassing file, but there must be further type magic getting in the way when print >> is used.

import sys

class tee(file):
   def write(self, text):
     sys.stdout.write(text)
     file.write(self, text)

fd = tee("output.txt", "w")
print >> fd, "Test 1"
fd.write("Test 2n")
$ python test.py
Test 2

$ cat output.txt
Test 1
Test 2

Using the dis module, we can tell that print >> is compiled into PRINT_ITEM_TO.

>>> def t(): print >> fd, "foo"
...
>>> import dis; dis.dis(t)
  1           0 LOAD_GLOBAL              0 (fd)
              3 DUP_TOP
              4 LOAD_CONST               1 ('foo')
              7 ROT_TWO
              8 PRINT_ITEM_TO
              9 PRINT_NEWLINE_TO
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE

and looking through ceval.c, searching for PRINT_ITEM_TO yields

 case PRINT_ITEM_TO:
    w = stream = POP();
    /* fall through to PRINT_ITEM */

case PRINT_ITEM:
    v = POP();
    if (stream == NULL || stream == Py_None) {
        w = PySys_GetObject("stdout");
        if (w == NULL) {
            PyErr_SetString(PyExc_RuntimeError,
                    "lost sys.stdout");
            err = -1;
        }
    }
    /* PyFile_SoftSpace() can exececute arbitrary code
       if sys.stdout is an instance with a __getattr__.
       If __getattr__ raises an exception, w will
       be freed, so we need to prevent that temporarily. */
    Py_XINCREF(w);
    if (w != NULL && PyFile_SoftSpace(w, 0))
        err = PyFile_WriteString(" ", w);
    if (err == 0)
        err = PyFile_WriteObject(v, w, Py_PRINT_RAW);


Any ideas why?


About this entry