Skip to content Skip to sidebar Skip to footer

Creating A Custom Sys.stdout Class?

What I'm trying to do is simply have the output of some terminal commands print out to a wx.TextCtrl widget. I figured the easiest way to accomplish this is to create a custom std

Solution 1:

sys.stdout is not a class, it's an instance (of type file).

So, just do:

class StdOut(object):
    def __init__(self,txtctrl):
        self.txtctrl = txtctrl
    def write(self,string):
        self.txtctrl.write(string)

sys.stdout = StdOut(the_text_ctrl)

No need to inherit from file, just make a simple file-like object like this! Duck typing is your friend...

(Note that in Python, like most other OO languages but differently from Javascript, you only ever inherit from classes AKA types, never from instances of classes/types;-).

Solution 2:

If all you need to implement is writing, there is no need to define a new class at all. Simply use createdTxtCtrl instead of StdOut(createdTxtCtrl), because the former already supports the operation you need.

If all you need to do with stdout is direct some programs' output there, not direct all kinds of stuff there, don't change sys.stdout, just instantiate the subprocess.Popen with your own file-like object (createdTxtCtrl) instead of sys.stdout.

Solution 3:

Here is a simple class that should cover most cases. By default, it just throws away the writes, but conditionally you can pass a handler to redirect the writes.

classTextIOTrap():
    name=None
    buffer=None
    encoding=None
    errors=None
    newlines=None
    line_buffering=Nonedef__init__(self, **args):
        self.write_handler = args.get('write_handler', None)
        self.name = args.get('name', '-')
    def__iter__(self):return []
    defclose(self):passdefdetach(self): passdeffileno(self):return0defflush(self):passdefisatty(self):returnFalsedefread(self, n=None): return''defreadable(self):returnFalsedefreadline(self, limit=-1):passdefreadlines(self, hint=-1):return []
    defseek(self, offset, whence=0): passdefseekable(self): returnFalsedeftell(self): return0deftruncate(self, size=None): passdefwritable(self): returnTruedefwrite(self, s):
        if self.write_handler andnot s == '\n': 
            self.write_handler(s)
        return0defwritelines(self, lines):
        ifisinstance(lines, list):
            for s in lines: self.write(s)

Trap writes to a list:

aTrappedStdout = []
_stdout_bk = sys.stdout
sys.stdout = TextIOTrap(write_handler=lambda s: aTrappedStdout.append(s))
print("TEST1")
print("TEST2")
sys.stdout = _stdout_bk
print(f"aTrappedStdout = {aTrappedStdout}")
# output: aTrappedStdout = ['TEST1', 'TEST2']

As a DEVNULL replacement:

DEVNULL=TextIOTrap()
_stdout_bk = sys.stdout
sys.stdout = DEVNULL
print("THIS WILL NOT PRINT")
sys.stdout = _stdout_bk
print("THIS WILL PRINT")

Solution 4:

Wouldn't sys.stdout = StdOut(createdTxtCtrl) create cyclical dependency? Try not reassigning sys.stdout to the class derived from sys.stdout.

Post a Comment for "Creating A Custom Sys.stdout Class?"