当 sys.stdout 被替换时,cmd.Cmd 中的 Python readline tab 补全
目前,我有一个使用 cmd.Cmd 模块作为命令行界面的应用程序,制表符补全功能完美运行。
现在,我想用另一个对象替换 sys.stdout (例如,为了捕获正在写入的内容。)
理论上,以下代码片段应该是完全透明的,因为每个 get/set 操作Std 对象被重定向到实际的 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()
例如,sys.stdout.fileno()
仍会打印 1。 但是,Cmd.cmd
的 readline tab-completion 现在不再起作用...
好吧,让我们从 file 继承。 (stdout 是一个文件对象。)
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()
现在我得到:
Traceback (most recent call last):
File "./shell.py", line 61, in <module>
print '#1'
ValueError: I/O operation on closed file
但是,以下断言不会失败:
assert not sys.stdout.closed
不知何故,我猜,Python 过度优化了某些东西,并绕过了 Std.write。
我应该做什么来替换标准输出,而不失去 readline 支持......?
乔纳森
-编辑-
我也在尝试替换 sys.stdin。 将其传递给 cmd.Cmd 不起作用,因为 raw_input 用于 readline 支持,而 Python 的 raw_input 不接受文件描述符。它会回退到分配给 sys.stdin 的任何 pty。
当我创建一个新的 pty(通过 os.openpty()),并将该对分配给 sys.stdin/out 时,通过该 pty 的 readline 自动完成功能完美地工作,但同样,当包装在代理对象中时,它可以工作,但没有自动完成功能。
试图理解 readline 的来源,但这并不容易: http://svn.python.org/projects/python /branches/release25-maint/Modules/readline.c
Currently, I have an application which uses the cmd.Cmd module for the command line interface, tab-completion works perfectly.
Now, I'd like to replace sys.stdout
, with another object (For example, in order to capture what's being written.)
Following snippet should be completely transparent in theory, as every get/set operation to the Std object is redirected to the 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, sys.stdout.fileno()
will still print 1.
However, the readline tab-completion of Cmd.cmd
does no longer work now...
Okay, let's inherit from 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 assertion does not fail:
assert not sys.stdout.closed
Somehow, I guess, Python is overoptimizing something, and bypassing Std.write.
What should I do to replace stdout, without loosing readline support...?
Jonathan
-edit-
I'm also trying to replace sys.stdin.
Passing it to cmd.Cmd does not work, because raw_input is used for readline support and Python's raw_input does not accept a file descriptor. It falls back to whatever pty is assigned to sys.stdin.
When I create a new pty (through os.openpty()), and assign this pair to sys.stdin/out, readline autocompletion through that pty works perfectly, but again, when wrapped in a proxy object, it works, but without autocompletion.
Trying to understand the source of readline, but it isn't easy:
http://svn.python.org/projects/python/branches/release25-maint/Modules/readline.c
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确切知道为什么替换
sys.stdout
不起作用,但无论如何,您可以通过将自己的文件对象传递给cmd.Cmd
。这是一个示例脚本(部分借自 PyMOTW),演示制表符补全:
对于您的目的而言,这是一种更好的处理方式,因为它确保您只会捕获
Cmd
实例生成的输出。请注意,您传入的文件对象也可用作
Cmd
实例上的stdout
属性。I don't know precisely why replacing
sys.stdout
does not work, but in any case you can fix your immediate problems by passing your own file object to the constructor forcmd.Cmd
.Here is an example script (partly borrowed from PyMOTW), that demonstrates tab-completion:
For your purposes, this is a much better way of doing things, because it ensures you will only be capturing the output that your
Cmd
instance produces.Note that the file object that you pass in is also available as a
stdout
attribute on theCmd
instance.