Создание собственного класса sys.stdout?

То, что я пытаюсь сделать, это просто вывести вывод некоторых команд терминала в виджет 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

Любые идеи по исправлению этого будут оценены.


person Duck    schedule 19.02.2010    source источник


Ответы (3)


sys.stdout не class, это экземпляр (типа 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, вы всегда наследуете только от классов AKA типов, никогда от экземпляров классов/типов;-).

person Alex Martelli    schedule 19.02.2010
comment
Я попробовал это, и это привело к: Трассировка (последний последний вызов): Файл blade_gui.py, строка 179, в подпроцессе OnNew.Popen('echo Hello World!',stdout=sys.stdout,shell=True) Файл C :\Python26\lib\subprocess.py, строка 614, в init errread, errwrite) = self._get_handles(stdin, stdout, stderr) Файл C:\Python26\lib\subprocess.py, строка 734, в _get_handles c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) AttributeError: объект «StdOut» не имеет атрибута «fileno» - person Duck; 19.02.2010
comment
subprocess может выполнять программы, написанные на любом языке (не только Python!), поэтому ему нужен настоящий файл уровня ОС (т. е. файл с FD, также известный как fileno). реальный файл уровня ОС (включая, к счастью, subprocess.PIPE, который позволяет вашему родительскому процессу получать выходные данные дочернего процесса, однако буферизация в дочернем процессе обычно означает, что это не то, что вам нужно, поэтому я всегда предлагаю вместо этого использовать pexpect или wexpect ). - person Alex Martelli; 19.02.2010
comment
вам нужно больше, чем просто write, вам также нужно flush, возможно, некоторые другие, в зависимости от того, как они будут использоваться. - person SimplyKnownAsG; 03.06.2014

Если все, что вам нужно реализовать, — это писать, то вообще не нужно определять новый класс. Просто используйте createdTxtCtrl вместо StdOut(createdTxtCtrl), потому что первый уже поддерживает нужную вам операцию.

Если все, что вам нужно сделать с stdout, это направить туда вывод некоторых программ, а не направлять туда всякие вещи, не меняйте sys.stdout, просто создайте экземпляр subprocess.Popen с вашим собственным файлоподобным объектом (createdTxtCtrl) вместо sys.stdout.

person Mike Graham    schedule 19.02.2010

Разве sys.stdout = StdOut(createdTxtCtrl) не создаст циклическую зависимость? Попробуйте не переназначать sys.stdout классу, производному от sys.stdout.

person Aleksa    schedule 19.02.2010