创建自定义的 sys.stdout 类?
我想做的事情很简单,就是把一些终端命令的输出显示到一个wx.TextCtrl控件里。我想,最简单的方法就是创建一个自定义的stdout类,并把它的写入功能重载成这个控件的写入功能。
stdout类:
class StdOut(sys.stdout):
def __init__(self,txtctrl):
sys.stdout.__init__(self)
self.txtctrl = txtctrl
def write(self,string):
self.txtctrl.write(string)
然后我会这样做:
sys.stdout = StdOut(createdTxtCtrl)
subprocess.Popen('echo "Hello World!"',stdout=sys.stdout,shell=True)
结果出现了以下错误:
Traceback (most recent call last):
File "mainwindow.py", line 12, in <module>
from systemconsole import SystemConsole
File "systemconsole.py", line 4, in <module>
class StdOut(sys.stdout):
TypeError: Error when calling the metaclass bases
file() argument 2 must be string, not tuple
如果有任何解决这个问题的想法,我会很感激。
4 个回答
0
我在PyPi上发布了一个叫做 tiotrap 的包,这个包里面有一个叫 TextIOTrap
的辅助类,用来管理文本输入输出流。
安装方法:
python3 -m pip install tiotrap
这个Trap会把数据写入一个列表,你也可以用这个方法来实现自己的处理方式,只需要把lambda替换成一个函数或方法的调用就可以了:
import tiotrap
aTrappedStdout = []
_stdout_bk = sys.stdout
sys.stdout = tiotrap.TextIOTrap(write_handler=lambda s: aTrappedStdout.append(s))
print("TEST1")
print("TEST2")
sys.stdout = _stdout_bk
print(f"aTrappedStdout = {aTrappedStdout}")
# output: aTrappedStdout = ['TEST1', 'TEST2']
下面是一个使用它来存储捕获数据的方法:
_stdout_bk = sys.stdout
tio_trap = tiotrap.TextIOTrap(store=True)
sys.stdout = tio_trap
print("TEST1")
print("TEST2")
sys.stdout = _stdout_bk
print(f"captured logs:\n{str(tio_trap)}\n~end~\n")
# output:
# captured logs:
# TEST1
# TEST2
# ~end~
它还可以作为跨平台的DEVNULL替代品:
_stdout_bk = sys.stdout
sys.stdout = tiotrap.DEVNULL
print("THIS WILL NOT PRINT")
sys.stdout = _stdout_bk
print("THIS WILL PRINT")
0
如果你只需要实现写入功能,其实根本不需要定义一个新类。你可以直接使用 createdTxtCtrl
,而不是 StdOut(createdTxtCtrl)
,因为前者已经支持你需要的操作。
如果你只是想把一些程序的输出导向标准输出,而不是把各种东西都导过去,那就不要去改 sys.stdout
。只需要用你自己的文件样的对象(createdTxtCtrl
)来实例化 subprocess.Popen
,而不是用 sys.stdout
。
17
sys.stdout
其实不是一个 类
,而是一个实例(它的类型是 file
)。
所以,你只需要这样做:
class StdOut(object):
def __init__(self,txtctrl):
self.txtctrl = txtctrl
def write(self,string):
self.txtctrl.write(string)
sys.stdout = StdOut(the_text_ctrl)
不需要从 file
继承,只要像这样简单地创建一个类似文件的对象就可以了!鸭子类型会帮到你……
(注意,在Python中,和大多数其他面向对象的语言一样,但和Javascript不同,你只会从类,也就是类型中继承,绝对不会从类/类型的实例中继承;-)。