redirector_output_trap.py
97 lines
| 3.4 KiB
| text/x-python
|
PythonLexer
Gael Varoquaux
|
r1422 | # encoding: utf-8 | ||
""" | ||||
Trap stdout/stderr, including at the OS level. Calls a callback with | ||||
the output each time Python tries to write to the stdout or stderr. | ||||
""" | ||||
__docformat__ = "restructuredtext en" | ||||
#------------------------------------------------------------------------------- | ||||
# Copyright (C) 2008 The IPython Development Team | ||||
# | ||||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#------------------------------------------------------------------------------- | ||||
#------------------------------------------------------------------------------- | ||||
# Imports | ||||
#------------------------------------------------------------------------------- | ||||
from fd_redirector import FDRedirector, STDOUT, STDERR | ||||
from IPython.kernel.core.file_like import FileLike | ||||
from IPython.kernel.core.output_trap import OutputTrap | ||||
class RedirectorOutputTrap(OutputTrap): | ||||
""" Object which can trap text sent to stdout and stderr. | ||||
""" | ||||
#------------------------------------------------------------------------ | ||||
# OutputTrap interface. | ||||
#------------------------------------------------------------------------ | ||||
def __init__(self, out_callback, err_callback): | ||||
gvaroquaux
|
r1459 | """ | ||
out_callback : callable called when there is output in the stdout | ||||
err_callback : callable called when there is output in the stderr | ||||
""" | ||||
Gael Varoquaux
|
r1422 | # Callback invoked on write to stdout and stderr | ||
self.out_callback = out_callback | ||||
self.err_callback = err_callback | ||||
# File descriptor redirectors, to capture non-Python | ||||
# output. | ||||
self.out_redirector = FDRedirector(STDOUT) | ||||
self.err_redirector = FDRedirector(STDERR) | ||||
# Call the base class with file like objects that will trigger | ||||
# our callbacks | ||||
OutputTrap.__init__(self, out=FileLike(self.on_out_write), | ||||
err=FileLike(self.on_err_write), ) | ||||
def set(self): | ||||
""" Set the hooks: set the redirectors and call the base class. | ||||
""" | ||||
self.out_redirector.start() | ||||
gvaroquaux
|
r1456 | self.err_redirector.start() | ||
Gael Varoquaux
|
r1422 | OutputTrap.set(self) | ||
def unset(self): | ||||
""" Remove the hooks: call the base class and stop the | ||||
redirectors. | ||||
""" | ||||
OutputTrap.unset(self) | ||||
Gael Varoquaux
|
r1423 | # Flush the redirectors before stopping them | ||
self.on_err_write('') | ||||
gvaroquaux
|
r1456 | self.err_redirector.stop() | ||
self.on_out_write('') | ||||
Gael Varoquaux
|
r1422 | self.out_redirector.stop() | ||
#------------------------------------------------------------------------ | ||||
# Callbacks for synchronous output | ||||
#------------------------------------------------------------------------ | ||||
def on_out_write(self, string): | ||||
""" Callback called when there is some Python output on stdout. | ||||
""" | ||||
Gael Varoquaux
|
r1423 | try: | ||
self.out_callback(self.out_redirector.getvalue() + string) | ||||
except: | ||||
# If tracebacks are happening and we can't see them, it is | ||||
# quasy impossible to debug | ||||
self.unset() | ||||
raise | ||||
Gael Varoquaux
|
r1422 | |||
def on_err_write(self, string): | ||||
""" Callback called when there is some Python output on stderr. | ||||
""" | ||||
Gael Varoquaux
|
r1423 | try: | ||
self.err_callback(self.err_redirector.getvalue() + string) | ||||
except: | ||||
# If tracebacks are happening and we can't see them, it is | ||||
# quasy impossible to debug | ||||
self.unset() | ||||
raise | ||||
Gael Varoquaux
|
r1422 | |||