Re: Python Embedding: redirecting output

Monty Brandenberg (montyb@hks.com)
9 Feb 1995 17:29:52 GMT

Hammond, Mark (@ JM) (MHammond@jm.cmutual.com.au) wrote:

: The simplest way of grabbing output is to override sys.stdout and
: sys.stderr. All that is required is that the object you redirect to has a
: "write" method.

: An apporach you could take would be to run_command() a command for
: re-assigning sys.stdout/err to one of your objects. Then run_command() the
: real command, and conther run_command() to restore it back. However, in
: some imbedded applications, it is often OK to redirect stdout once at the
: start for the life of the application.

That's partly the idea. In my application, Python is truly an embedded
component. It doesn't have control of the command stream and is
driven by requests from a distributed user interface running well
above it. I believe that something like the StringIO package Guido
mentioned or the code Steve posted will get me close to what I want
(having only dove into Python code a few days ago I'm still on the
learning curve) but fitting it into an application raises some
general design questions about embedding.

1. Source of input. 'run_command()' or something like it seems
to be correct. As an embedded component, Python cannot assume
that it can poll/sleepwait for input. It may have to be
driven from the top as in my application. However, as
Python becomes thread-friendly someone may choose to
run Python in its own thread. In this case, it is suitable
to have Python perform a sleeping read on a modified or
subclassed fileobject that performs interthread communication.

2. Redirecting output and error. Everyone seems to understand
this so I won't elucidate much. Basically, the embedding
application wants a sequence something like:

Clear output and error buffers.
Execute Python command(s).
Return output and error buffers to calling code.

Posted code seems to do most of that though I'm having
difficulty with the latter at the moment.

3. Exception handling. Executing a Python command may be part
of a larger transaction in the embedding application. Such
an application may want to specify it's own top-level
exception handling. E.g. allow Python to emit an
elaborated exception message to sys.stdout or sys.stderr,
return the exception status and reason to the caller
of run_command() or run_script(), etc. This may actually
be available now, I just haven't found the right way to
access it.

4. Mechanism for providing the above. This is partly a matter
of aesthetics. Most suggestions so far have centered
on a methods based on Python scripts to redefine classes
to do IO and that is elegant from a language-user's
perspective. But it could also be specified as part of
an initializion step via C interface. In this way,
run_command() and friends are never invoked until *after*
I/O and exception handling are pointing to the desired
application facilities. There is no interim state where
Python might take an exception or babble to the wrong
data stream. There is no dependency on the availability
of external modules such as StringIO. From an application
developer's point of view, this is somewhat more elegant
and trustworthy. Consider rewriting the standard Python
main program as an embedded application:

main() {
initall();

// Construct standard fileobjects for
// sys.stdin, sys.stdout, and sys.stderr
// from main's stdin, stdout, stderr

// Establish Python exception handling
// mechanism (built-in default?).

for (;;) {
readline(...);
run_command(...);
}
}

Comments? And thanks to everyone for the replies so far, they are
appreciated.

monty