创建自定义 sys.stdout 类?

发布于 2024-08-22 13:49:14 字数 840 浏览 5 评论 0原文

我想做的只是将一些终端命令的输出打印到 wx.TextCtrl 小部件。我认为完成此操作的最简单方法是创建一个自定义标准输出类并将写入函数重载到小部件的写入函数。

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

任何修复此问题的想法将不胜感激。

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 stdout class and overload the write function to that of the widget.

stdout class:

class StdOut(sys.stdout):
    def __init__(self,txtctrl):
        sys.stdout.__init__(self)
        self.txtctrl = txtctrl

    def write(self,string):
        self.txtctrl.write(string)

And then I would do something such as:

sys.stdout = StdOut(createdTxtCtrl)    
subprocess.Popen('echo "Hello World!"',stdout=sys.stdout,shell=True)

What results is the following error:

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

Any ideas to fix this would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

゛清羽墨安 2024-08-29 13:49:15

如果您需要实现的只是编写,则根本不需要定义新类。只需使用 createdTxtCtrl 而不是 StdOut(createdTxtCtrl),因为前者已经支持您需要的操作。

如果您需要对 stdout 做的只是将某些程序的输出定向到那里,而不是直接将所有类型的内容定向到那里,则不要更改 sys.stdout,只需实例化 subprocess.Popen code> 使用您自己的类文件对象 (createdTxtCtrl) 而不是 sys.stdout

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.

红焚 2024-08-29 13:49:15

我已经将一个名为 tiotrap 的包部署到 PyPi,其中包含 TextIOTrap 辅助类用于管理 TextIO 流。

安装:

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

I have deployed a package to PyPi called tiotrap, which contains TextIOTrap helper class for managing TextIO Streams.

Installation:

python3 -m pip install tiotrap

Trap writes to a list, you could implement your own handler with this method as well, just substitute the lambda with a function/method call:

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']

Here is a way you can use it to store the captured data:

_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~

As a cross platform DEVNULL replacement:

_stdout_bk = sys.stdout
sys.stdout = tiotrap.DEVNULL
print("THIS WILL NOT PRINT")
sys.stdout = _stdout_bk
print("THIS WILL PRINT")
会发光的星星闪亮亮i 2024-08-29 13:49:15

sys.stdout = StdOut(createdTxtCtrl) 不会创建循环依赖吗?尝试不要将 sys.stdout 重新分配给从 sys.stdout 派生的类。

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

只有影子陪我不离不弃 2024-08-29 13:49:14

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 中,与大多数其他 OO 语言一样,但与 Javascript 不同,你只能从类 AKA 类型继承,从不从 < em>类/类型的实例;-)。

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;-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文