Tkinter mainloop неожиданно завершает работу после произнесения текста с помощью pyttsx - PullRequest
0 голосов
/ 27 декабря 2011

Я создаю небольшую программу, которая использует tkinter и pyttsx для взаимодействия с пользователем.По какой-то причине сценарий завершает работу после того, как он сказал «нажал кнопку», в то время как он должен оставаться в основном цикле.Даже более странно, он даже не проходит «контрольную точку», которую я добавил ниже основного цикла.

Вот упрощенная версия кода, который выдает ошибку:

import Tkinter as tk
import pyttsx

def button_click():
    engine.say('button clicked')
    engine.runAndWait()

engine = pyttsx.init()

root = tk.Tk()
gameframe = tk.Frame(root)
gameframe.pack()
readybutton = tk.Button(gameframe, text = 'click', command = button_click)
readybutton.pack()

root.mainloop()

print('checkpoint')

Как решить эту проблему?

Обновление: через Google я обнаружил некоторые признаки того, что эта проблема может иметь отношение как к tkinter, так и к pyttsx с использованием циклов событий, а также с тем, как модули Apple Foundation и / или ObjC обрабатывают события.Так как я новичок в Python, я не очень хорошо понимаю это, но некоторые из вас могут, см. http://comments.gmane.org/gmane.comp.python.pyobjc.devel/5965.

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

import os

phrase = 'button clicked'
os.system("/usr/bin/say " + phrase)

Это хорошо работает, также в сочетании с tkinter: -)

Ответы [ 2 ]

0 голосов
/ 01 января 2012

pyttsx разваливается, когда вы вызываете его методы Engine из разных потоков, даже если они никогда не перекрываются во времени.(Не только runAndWait , но и такие вещи, как скажем тоже.) startLoop и runAndWait block.

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

Если вы используете startLoop , будьте осторожны, чтобы не дать обратному вызову Finished-Utterance вернуться, когда очередь команд пуста.или вы не сможете снова получить доступ к циклу, но startLoop также не вернется.Я думаю, что у меня были проблемы с runAndWait .

Кроме того, вызов Engine.stop из обратного вызова, кажется, заставляет вещи перестать работать должным образом.(Но вы также не можете вызывать его откуда-либо еще.) Никогда не вводите скажем пустую строку или не-ascii символ.(Возможно, зависит от платформы).

0 голосов
/ 27 декабря 2011

Что заставляет вас думать, что он выходит из основного цикла? Если он не доходит до этой последней инструкции print, основной цикл не «завершается», ваша программа падает. Основываясь на доказательствах, которые вы приводите, сбой происходит по методу engine.runAndWait().

Если ваша программа не падает, и вы действительно имеете в виду, что программа больше не отвечает на события, то единственное объяснение состоит в том, что engine.runAndWait() блокирует. Почему это происходит, я не знаю, потому что я никогда не использовал pyttsx, хотя в документации для runAndWait говорится, что он будет блокироваться до тех пор, пока не будут обработаны все события в очереди. Возможно, он думает, что в очереди еще что-то есть.

...