如何同时使用Python的print()函数与pyttsx3模块的语音播报功能?
解决print()与语音播报同步的方案
我完全懂你的烦恼——重复写两次相同的文本不仅麻烦,还容易写错!这里有几个实用的方法,能让你只写一次内容,同时完成屏幕打印和语音播报:
方案1:自定义一个“打印+播报”函数(最简单)
直接写一个封装好的函数,把print()和engine.say()的逻辑整合在一起,替换原来的重复调用就行:
import pyttsx3 # 初始化语音引擎 engine = pyttsx3.init() def say_and_print(text): # 先打印到屏幕 print(text) # 再添加到语音播报队列 engine.say(text) # 现在直接调用这个函数就搞定了 say_and_print('Sally sells seashells by the seashore.') say_and_print('The quick brown fox jumped over the lazy dog.') # 最后执行所有播报任务 engine.runAndWait()
这个方案的优点是直观易懂,新手也能快速上手,完全不用改原有代码的逻辑,只是把重复的两行换成一行调用。
方案2:重写内置print函数(不用改原有代码)
如果你已经写了大量print()调用,不想一个个替换,那就直接重写Python的内置print函数,让所有print自动触发播报:
import pyttsx3 import builtins engine = pyttsx3.init() # 先保存原来的print函数,后面可以恢复 original_print = builtins.print def custom_print(*args, **kwargs): # 先执行原生的print逻辑 original_print(*args, **kwargs) # 处理print的多参数情况(比如print("Hello", "World")) # 把所有参数转成字符串,再按sep参数拼接 text_parts = map(str, args) if 'sep' in kwargs: text = kwargs['sep'].join(text_parts) else: text = ' '.join(text_parts) # 添加到语音队列 engine.say(text) # 替换内置的print函数 builtins.print = custom_print # 现在直接用原来的print就自动播报了! print('Sally sells seashells by the seashore.') print('The quick brown fox jumped over the lazy dog.') # 甚至多参数、自定义分隔符的情况也能处理 print("Hi", "there", sep="||") engine.runAndWait()
这个方案适合已有大量代码的场景,完全不用修改原有print调用,所有打印内容都会自动转成语音播报,兼容性拉满。
方案3:用上下文管理器(临时启用播报)
如果你只需要某一段代码的print触发播报,不想全局修改,那就用上下文管理器来实现临时替换:
import pyttsx3 import builtins from contextlib import contextmanager engine = pyttsx3.init() @contextmanager def speak_on_print(): # 保存原生print original_print = builtins.print def custom_print(*args, **kwargs): original_print(*args, **kwargs) text_parts = map(str, args) text = kwargs.get('sep', ' ').join(text_parts) engine.say(text) # 替换print builtins.print = custom_print try: yield finally: # 退出上下文后恢复原生print builtins.print = original_print # 使用示例:只有with块内的print会播报 with speak_on_print(): print('这段内容会被打印+播报') print('这段也是哦') # 出了with块,print就变回原来的样子了 print('这段只会打印,不会播报') engine.runAndWait()
这个方案的灵活性最高,适合局部代码需要播报的场景,避免全局修改带来的意外副作用。
小提示
- 记得最后一定要调用
engine.runAndWait(),否则语音队列里的内容不会被执行;如果是长时间运行的程序,可以定期调用这个方法来处理播报任务。 - 如果打印的是非字符串内容(比如数字、对象),上面的方案已经帮你转成字符串了,不用担心报错。
内容的提问来源于stack exchange,提问作者RajTech King
相关产品推荐
相关产品推荐

