redirect python output + extension type with own print method = FAILS

doug doug_bartholomew99 at yahoo.com
Sat Aug 11 00:57:33 EDT 2001


hello,

BOTTOMLINE: Why when python's output is redirected by overriding
sys.stdout, would a user-defined type's print method not be
accessible?

*** PART 1 ***
i have successfully redirected python output using a technique which i
think is a fairly common one.  It involves overriding sys.stdout and
sys.stderr with objects which have a "write" method.  This begins with
a function that's prototyped as:

   static PyObject* StdOut_Write(PyObject* Self, PyObject* Args) 

which is followed up by:

   static PyMethodDef StdOut_Methods[] =
   {
      { "write", StdOut_Write, 1 },
      { NULL,    NULL,           }  
   };

and:

   PyObject* py_out = Py_InitModule("stdout", StdOut_Methods);
   PySys_SetObject("stdout", py_out);

and all this works perfectly fine.  When run, python succesfully
redirects to the correct place.  Great.  (FWIW, redirection goes to a
window in an MFC app.)

*** PART 2 ***
Forget that we have done the above and create an extension type that
has its own print method.  To make it easy, take the xxmodule.c that
comes with the standard distribution source and just add a print
method.  For instance:

   static int
   XXo_print(XxoObject *self, FILE *fp, int flags)
   {  
      char mystring[] = "Spam is good!";
      fprintf(fp, "%s", mystring);
      return 0;
   }

and of course the print slot needs to be filled in in type object
structure:

   static PyTypeObject Xxo_Type = {
   ...
      (printfunc)XXo_print,    /*tp_print*/
   ...

When this xx.pyd module is loaded into a python session run in console
mode in w2k, everything works as expected.  This is what i see:

   C:\test>python
   ActivePython 2.1.1, build 212 (ActiveState)
   Python 2.1.1 (#20, Jul 26 2001, 11:38:51) [MSC 32 bit (Intel)] on
win32
   Type "copyright", "credits" or "license" for more information.
   >>> from xx import *
   >>> foo = new()
   >>> print foo
   Spam is good!
   >>>

*** HERE IS THE PROBLEM! ***
When i combine both steps above, the print method of the XXo object
fails.  IOW, when i redirect python's output by overriding sys.stdout
with an object that has a "write" method AND then try to print a
user-defined type with its own print method, instead of the print
method being accessed correctly, i just get its memory address back. 
This is what i see:

   ActivePython 2.1.1, build 212 (ActiveState)
   Python 2.1.1 (#20, Jul 26 2001, 11:38:51) [MSC 32 bit (Intel)] on
win32
   Type "copyright", "credits" or "license" for more information.
   THIS OUTPUT IS BEING REDIRECTED
   >>>from xx import *
   >>>foo = new()
   >>>print foo
   <Xxo object at 008592A8>
   
   >>>


I have looked at python's source code and noticed that the function
PyObject_Print in file object.c will print an object's memory address
if both the print method and repr method are NULL.  I presume this is
the particular code that python to cause the <Xxo object at 008592A8>
msg above:

      ...
      else if (op->ob_type->tp_print == NULL) {
         if (op->ob_type->tp_repr == NULL) {
            fprintf(fp, "<%s object at %p>",
               op->ob_type->tp_name, op);
         }
      ...

So my question is, why when python's output is redirected by
overriding sys.stdout, would a user-defined type's print method not be
accessible?  I am using MSVC++ 6.0 on w2k.

any help is greatly appreciated,

doug
doug_bartholomew99 at yahoo.com



More information about the Python-list mailing list