2013-12-06 3 views
0

Это мой первый набег на резьбу, поэтому извиняюсь за любые очевидные ошибки.Проверка потокобезопасности в python?

У меня есть виджет PyQt, из которого новый процесс, prog, запускается в другом потоке. В моей основной теме я также перенаправляю stdout только для чтения QTextEdit. Тем не менее, я получаю ошибки, связанные с рекурсией, и я беспокоюсь, что мои потоки мешают друг другу так, что оператор печати переходит в бесконечный цикл. Я получаю только эти ошибки, если я запускаю prog из графического интерфейса пользователя, а не из командной строки. Мой stdout редирект с помощью кода в this SO answer

В псевдо-коде, это в основном то, что я получил:

gui.py

class widget(QWidget): 
    def __init__(self): 
    self.button = QPushButton("GO!", self) 
    self.button.clicked.connect(self.start) 

    def start(self): 
    self.thread = TaskThread() 
    sys.stdout = EmittingStream(textWritten = self.outputText) 
    self.thread.start() 

    def outputText(self): 
    #as in answer provided in link (EmittingStream in separate module) 

prog.py

class TaskThread(QThread): 
    def run(self): 
    ''' 
     Long complicated program; putting in simpler code here (e.g. loop printing to 10000) doesn't reproduce errors 
    ''' 
  • Есть ли способ узнать, вызвана ли моя рекурсия бесконечным циклом или чем-то еще?
  • Является ли мой код явно небезопасным?
  • Как вы гарантируете, что функции являются потокобезопасными? (Ссылки на учебные пособия/книги будут полезными!)

ответ

0

Это сложно, но я думаю, что ваш код является поточно-небезопасных. В частности, глядя на другие ответы stackoverflow (here и here), вам не следует обращаться к объекту Qt GUI из другого потока, кроме того, в котором он был создан (даже QThread).

Поскольку любой вызов print в вашем коде теперь обращается к объекту GUI Qt, кажется, что это очень небезопасный поток.

Мое предложение, чтобы сделать его безопасным было бы:

  1. Есть QThread, внутри которого вы создали экземпляр выходного окна (это поточно для доступа к объекту Qt GUI из потока это было созданный в, и его не нужно создавать в основном потоке ). Объекты Qt GUI не являются реентерабельными и должны быть созданы и использованы только в основном потоке, см. here. Таким образом вам понадобится QThread для публикации событий на (используя механизм Qt сигналов/слотов, который может быть корректным для потоковой передачи)
  2. Имейте этот QThread, блокирующий rea ding из Python Queue. Когда он получает что-то из очереди, он помещает его в текстовое поле Qt. отправляет его обратно в основной поток, а основной поток будет обновлять окно вывода.
  3. Измените свой EmmittingStream, чтобы поместить вещи в Queue, а не непосредственно в поле вывода Qt.
+0

Моя первоначальная идея была неправильной, если вы хотите быть потокобезопасной, вам нужно отправить события из QThreads обратно в основной поток, используя QApplication.postEvent() (отлично в PyQt, утечка памяти в PySide) или использовать встроенные сигналы/slots QThreads и подключить слот из основного потока к сигналу в QThread (это соединение должно быть выполнено из основного потока или метода __init__ вашего QThread) (последний параметр сигнала/слота не пропускает память в PySide) Извинения за допущенные ошибки –

0

Я вижу, что вы обнаружили, где находится ошибка. Но без кода не так много, что я могу сказать.

Наполняя ваши потребности в направлении, я укажу вам на профили Python. Поскольку похоже, что вам нужны инструменты профилирования python.

http://docs.python.org/2/library/profile.html

и ответ на эту тему

How can you profile a Python script?

0

В приложении Qt вы должны использовать один поток для обработки всей части gui. Вы можете использовать другие потоки для вычислений, но не для пользовательского интерфейса.

Просто публикуйте сообщения об обновлениях в очереди в рабочих потоках и используйте основной поток, чтобы получить эти сообщения и обновить графический интерфейс.

+0

Извините, возможно, я недостаточно хорошо себя объяснил. Насколько я понимаю, у меня есть часть GUI в 1 потоке, а часть вычисления - в другом потоке. К сожалению, ваш второй абзац прошел прямо над моей головой. Мне лучше пойти и почитать книгу! – ChrisW

Смежные вопросы