2012-01-07 7 views
5

Actualmente, tengo una aplicación que usa el módulo cmd.Cmd para la interfaz de línea de comandos, la terminación de pestañas funciona perfectamente.Python read-tab-completion en cmd.Cmd, cuando sys.stdout ha sido reemplazado

Ahora, me gustaría reemplazar sys.stdout, con otro objeto (por ejemplo, con el fin de capturar lo que está siendo escrita.)

siguiente fragmento debe ser totalmente transparente en teoría, ya que cada GET/operación de establecimiento de el objeto Std se redirige al 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() 

Por ejemplo, sys.stdout.fileno() se imprimirá 1. Sin embargo, el readline para rellenar la ficha de Cmd.cmd qué ya no funciona en este momento ...

Está bien, vamos a heredan de archivo. (Stdout es un objeto de archivo.)

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() 

Y ahora me sale:

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

Sin embargo, la siguiente afirmación no falla:

assert not sys.stdout.closed 

De alguna manera, supongo, Python es sobre-optimizando algo, y evitando Std.write.

¿Qué debo hacer para reemplazar stdout, sin perder el soporte de readline ...?

Jonathan

operación -Editar-

También estoy tratando de reemplazar sys.stdin. Pasarlo a cmd.Cmd no funciona, porque raw_input se usa para soporte de lectura y Python's raw_input no acepta un descriptor de archivo. Se reduce a lo que se le haya asignado a sys.stdin.

Cuando creo un pty nuevo (a través de os.openpty()), y asigno este par a sys.stdin/out, la autocompleción de readline a través de ese pty funciona perfectamente, pero de nuevo, cuando está envuelto en un objeto proxy, funciona , pero sin autocompletar

tratando de comprender el origen de readline, pero no es fácil: http://svn.python.org/projects/python/branches/release25-maint/Modules/readline.c

Respuesta

1

No sé exactamente por qué la sustitución de sys.stdout no funciona, pero en cualquier caso se puede arreglar sus problemas inmediatos pasando su propio objeto de archivo al constructor para cmd.Cmd.

Aquí es un script de ejemplo (en parte tomado de PyMOTW), que demuestra para rellenar la ficha:

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() 

para sus propósitos, esta es una mejor manera de hacer las cosas, ya que asegura que sólo será capturando la salida que produce su instancia Cmd.

Tenga en cuenta que el objeto de archivo que pase también está disponible como un atributo stdout en la instancia Cmd.

+0

Gracias, pero esto realmente no ayuda. En 'cmd.Cmd .__ init__' se comprueba si stdout es None, si ese es el caso, tiene una reserva para sys.stdout. Entonces, es exactamente lo mismo, como asignar a sys.stdin/out. –

+0

@JonathanSlenders. No habría ofrecido la solución sin probarla primero. Para mí, soluciona el problema con la finalización de pestañas. No hice ninguna prueba para 'stdin', porque no era parte de tu pregunta original, pero sí leí la documentación de [cmd.Cmd] (http://docs.python.org/library/cmd.html # cmd.Cmd) y [use_rawinput] (http://docs.python.org/library/cmd.html#cmd.Cmd.use_rawinput), que parecen tener información relevante sobre ese problema. – ekhumoro

+0

@JonathanSlenders. He actualizado mi respuesta con el script que usé para probar. – ekhumoro

Cuestiones relacionadas