Захват stdout из импортированного модуля в wxpython и отправка его в textctrl без блокировки графического интерфейса

Есть много очень похожих вопросов, но я не могу найти ни одного, который бы относился конкретно к тому, что я пытаюсь сделать.

У меня есть симуляция (написанная на SimPy), для которой я пишу графический интерфейс, основной вывод симуляции - это текст - на консоль из операторов print. Теперь я подумал, что самым простым способом было бы создать отдельный модуль GUI.py и импортировать в него мою программу моделирования:

import osi_model

Я хочу, чтобы все операторы печати были захвачены графическим интерфейсом и отображались внутри Textctrl, и здесь есть бесчисленные примеры таких строк:

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        <general frame initialisation stuff..>

        redir=RedirectText(self.txtCtrl_1)
        sys.stdout=redir

class RedirectText:
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl

    def write(self,string):
        self.out.WriteText(string)

Я также запускаю симуляцию с кнопки «Пуск»:

def go_btn_click(self, event):
    print 'GO'
    self.RT = threading.Thread(target=osi_model.RunThis())
    self.RT.start()

Все это работает нормально, и выходные данные модуля моделирования захватываются TextCtrl, за исключением того, что графический интерфейс блокируется и перестает отвечать - мне все еще нужно, чтобы он был доступен (как минимум, чтобы была кнопка «Стоп»). Я не уверен, что это неудачная попытка создать новый поток, который я сделал здесь, но я предполагаю, что на каком-то этапе этого процесса потребуется новый поток.

Люди предлагают использовать wx.CallAfter, но я не уверен, как это сделать, учитывая, что импортированный модуль не знает о wx, а также я не могу реально пройти через всю архитектуру симуляции и изменить все операторы печати на wx .CallAfter, и любая попытка захватить оболочку из импортированной программы моделирования приводит к сбою программы.

Есть ли у кого-нибудь идеи о том, как мне лучше всего этого добиться? Так что все, что мне действительно нужно, это чтобы весь текст консоли был захвачен TextCtrl, в то время как графический интерфейс остается отзывчивым, а весь текст поступает исключительно из импортированного модуля.

(Кроме того, вторичный вопрос относительно кнопки «Стоп» - это плохой тон просто убить поток симуляции?).

Спасибо,

Дункан


person incidentnormal    schedule 12.04.2012    source источник
comment
Я бы посоветовал опубликовать отдельный вопрос для вашего запроса о кнопке остановки. Это не форум, поэтому лучше задавать разные вопросы по отдельности.   -  person Soviut    schedule 16.11.2012


Ответы (2)


Я бы посоветовал изучить эту статью WX wiki о длительных задачах.

В нем конкретно рассматривается ситуация, с которой вы имеете дело с использованием кнопки «Пуск», чтобы стать длительным процессом. Приведено несколько различных примеров с использованием различных методов, таких как потоки и обработчики простоя.

person Soviut    schedule 16.11.2012

Я думаю, вам придется перенаправить stdout в файл журнала (или простую базу данных SQLite?), А затем использовать свой поток, чтобы проверить файл журнала на наличие обновлений, которые он затем передаст в графический интерфейс с помощью wx.CallAfter или аналогичного. Возможно, вы сможете использовать что-то вроде сервера сокетов, построенного на Python: http://wiki.wxpython.org/AsynchronousSockets < / а>. Я думаю, что в кулинарной книге wxPython тоже упоминалось что-то об использовании RPC-сервера (вероятно, этот: http://docs.python.org/library/simplexmlrpcserver.html), но подробностей я не помню.

Вам также следует попробовать задать вопрос в официальном списке рассылки wxPython. Они там очень дружелюбны.

person Mike Driscoll    schedule 17.04.2012