Python readline-tab tab in cmd.Cmd when sys.stdout was replaced

I currently have an application that uses the cmd.Cmd module for the command line interface, tab execution works fine.

Now I would like to replace sys.stdoutwith another object (for example, to record what is being recorded.)

The following snippet should be completely transparent in theory, since each get / set operation for the Std object is redirected to actial sys.__stdout__.

class Std(object):
    def __getattribute__(self, name):
        if name in ('__getattribute__', '__setattr__'):
            return object.__getattribute__(self, name)
        else:
            return getattr(sys.__stdout__, name)

    def __setattr__(self, name, value):
        setattr(sys.__stdout__, name, value)

sys.stdout = Std()

For example, it sys.stdout.fileno()will print 1. However, completing the readline bookmark Cmd.cmdnow no longer works ...

Well, let it inherit from the file. (stdout is a file object.)

class Std(file):
    def __init__(self):
        pass
    def __getattribute__(self, name):
        if name in ('__getattribute__', '__setattr__'):
            return object.__getattribute__(self, name)
        else:
            return getattr(sys.__stdout__, name)

    def __setattr__(self, name, value):
        setattr(sys.__stdout__, name, value)

sys.stdout = Std()

And now I get:

Traceback (most recent call last):
  File "./shell.py", line 61, in <module>
    print '#1'
ValueError: I/O operation on closed file

However, the following statement is not interrupted:

assert not sys.stdout.closed

Somehow, I think, Python redefines something and bypasses Std.write.

, stdout, readline...?

-edit -

sys.stdin. cmd.Cmd , raw_input readline, Python raw_input . , pty sys.stdin.

pty ( os.openpty()) sys.stdin/out, readline pty , , -, , .

readline, : http://svn.python.org/projects/python/branches/release25-maint/Modules/readline.c

+5
1

, sys.stdout , , cmd.Cmd.

script ( PyMOTW), :

import sys, cmd

class Std(object):
    def __getattribute__(self, name):
        if name in ('__getattribute__', '__setattr__'):
            return object.__getattribute__(self, name)
        else:
            return getattr(sys.__stdout__, name)

    def __setattr__(self, name, value):
        setattr(sys.__stdout__, name, value)

class HelloWorld(cmd.Cmd):
    FRIENDS = [ 'Alice', 'Adam', 'Barbara', 'Bob' ]

    def do_greet(self, person):
        "Greet the person"
        if person and person in self.FRIENDS:
            greeting = 'hi, %s!' % person
        elif person:
            greeting = "hello, " + person
        else:
            greeting = 'hello'
        print greeting

    def complete_greet(self, text, line, begidx, endidx):
        if not text:
            completions = self.FRIENDS[:]
        else:
            completions = [f for f in self.FRIENDS
                           if f.startswith(text)]
        return completions

    def do_EOF(self, line):
        return True

if __name__ == '__main__':

    HelloWorld(stdout=Std()).cmdloop()

-, , , Cmd.

, stdout Cmd.

+1

All Articles