to-speech 模塊說一個串列,我使用的音頻模塊是混音器形式 pygame。當我開始播放音頻時,無法與 tkinter 程式互動,如果我移動視窗,音頻就會停止。我認為某種執行緒可以解決這個問題,但我不確定它是如何作業的。
問題
Tkinter 視窗凍結。
目標
能夠在播放音頻時與程式進行互動。
代碼
import tkinter as tk
from gtts import gTTS
from io import BytesIO
import pygame
window = tk.Tk()
window.geometry("800x600")
window.resizable(0, 0)
def speak(text,language="en",accent="com"):
mp3_fp = BytesIO()
phrase = gTTS(text=text,lang=language,tld=accent)
phrase.write_to_fp(mp3_fp)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(mp3_fp,"mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.delay(10)
pygame.event.poll()
def play():
data = list([boy,girl,pink,blue])
for i in data:
speak(i)
window.mainloop()
代碼說明
將play()字典Eg Boy、Girl中的每個值分別傳遞到speak()它們一個接一個連續播放的位置
在speak()來自文本轉語音模塊 ( gTTS )的音頻pygame.mixer中,當最后一個單詞有被說。
uj5u.com熱心網友回復:
首先,您需要發布演示問題所需的最少代碼。你沒有這樣做。幸運的是,這是一個眾所周知的“問題”,無需匯入四個庫并圍繞您提供的內容構建應用程式即可輕松回答。
其次 - 在您提供的代碼中,data = list[boy,girl,pink,blue]甚至不是正確的語法。應該是data = list(["boy", "girl", "pink", "blue"])。您必須發布運行代碼才能獲得最佳答案。
講座結束。
問題是傳統的未經修改的 Python 在單個執行緒中運行。如果您想知道為什么會這樣,那么我邀請您研究 GIL(全域解釋器鎖)以獲取更多背景資訊。
只有一個執行緒,當 PyGame 正在做某事時,執行緒很忙,TkInter 停止回應輸入,反之亦然——當 TkInter 處于某事的中間時,你會發現 PyGame 停止回應。
你可以用這個來證明這個現象:
import tkinter as tk
import time
def delay():
time.sleep(10)
def main():
root = tk.Tk()
tk.Button(root, text="Test Me", command=delay).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
當您運行此程式時,您會看到按鈕被按下,當應用程式進入睡眠狀態時按鈕保持按下狀態,并且按鈕在喚醒之前不會回到未單擊狀態。
我知道解決您的特定問題的唯一方法是在單獨的執行緒上運行 TkInter 和/或 PyGame。
您將不得不閱讀 Python 的Threading()模塊。你可以從這里開始。我瀏覽過它,它似乎很完整。
只是為了證明區別:
import tkinter as tk
import time
import threading
def delay():
print("Delay started...")
time.sleep(10)
print("... and finished.")
def dispatchDelayToThread():
t = threading.Thread(target=delay)
t.start()
def main():
root = tk.Tk()
tk.Button(root, text="Test Me", command=dispatchDelayToThread).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
我什至沒有真正改變任何代碼!我添加了一個函式來調度我已經撰寫的代碼,然后將按鈕更改為呼叫調度程式而不是代碼。很容易實作。
運行它,您會看到按鈕立即回傳到就緒狀態。如果你從命令列運行它,你會看到當你進入執行緒時它會列印一行,當執行緒完成時會列印另一行。更酷的是,如果您連續三次單擊該按鈕,您將收到三個“開始”訊息,然后是三個“完成”訊息。
要使用您自己的代碼演示此執行緒:
import pygame
import tkinter as tk
import io
import gtts
import threading
def speak(text,language="en",accent="com"):
mp3_fp = io.BytesIO()
phrase = gtts.gTTS(text=text,lang=language,tld=accent)
phrase.write_to_fp(mp3_fp)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(mp3_fp,"mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.delay(10)
pygame.event.poll()
def dispatchPlay():
t = threading.Thread(target=play)
t.start()
def play():
data = list(["boy", "girl", "pink", "blue"])
for i in data:
speak(i)
def main():
root = tk.Tk()
root.geometry('300x200')
tk.Button(root, text="This is a clicky button", command=dispatchPlay).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
通常,您會將用戶界面放在一個執行緒上,如果是游戲,則將幀更新放在另一個執行緒上,將聲音放在另一個執行緒上,將網路連接放在一個執行緒上等等,所有這些都通過某種訊息傳遞系統聯系在一起。
但是請注意,在傳統的未經修改的 Python 中,任何時候都只有一個執行緒在運行!您可以生成一百個執行緒,但一次只能運行其中一個。Python 不擅長多執行緒計算密集型任務,但擅長執行緒化 I/O 的東西,而這些東西你通常只是花時間等待。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/512044.html
