Kivy开发实时麦克风录音软件报__init__()意外参数__no_builder错误
问题描述
开发基于Kivy的实时麦克风数据采集软件时,程序运行持续抛出错误:TypeError: __init__() got an unexpected keyword argument '__no_builder'
逐行排查代码未定位问题根源,开发编辑器为Atom,项目包含.py代码文件与.kv规则文件。
错误根因
核心触发原因是自定义组件Logic的构造方法不符合Kivy组件的编写规范:
- Kivy加载KV规则实例化自定义组件时,会自动传入包括
__no_builder在内的多个关键字参数,但Logic类的__init__方法没有定义参数接收这些关键字,也没有在调用父类构造方法时透传参数,直接触发参数不匹配错误。 - 代码中还存在3处会导致后续运行异常的附带问题:
- 音频采集函数中
RATE : 44100是类型注解语法,不是变量赋值,运行时会抛出RATE未定义错误 - 调用RMS计算方法时模块名书写错误,导入的是
audioop模块,代码中写为audio.rms - KV文件中使用了
Graph组件,但Python代码中未导入该组件类,KV规则无法识别组件
- 音频采集函数中
修复方案
按以下步骤修改代码即可解决问题:
- 修正
Logic类的构造方法,添加**kwargs接收框架传入的关键字参数,并透传给父类构造方法:
class Logic(BoxLayout): def __init__(self, **kwargs): super(Logic,self).__init__(**kwargs) self.plot = MeshLinePlot(color=[1,0,0,1])
- 修正音频采集函数的语法错误:
- 将
RATE : 44100改为赋值语句RATE = 44100 - 将
mx = audio.rms(data,2)改为mx = audioop.rms(data,2)
- 将
- 在Python文件头部补全
Graph组件的导入语句:
from kivy.garden.graph import Graph
- (可选优化)将程序启动逻辑放入
if __name__ == "__main__":判断块中,避免模块被导入时自动启动线程和程序。
修正后完整Python代码
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.garden.graph import MeshLinePlot, Graph from kivy.clock import Clock from threading import Thread import audioop import pyaudio from kivy.core.window import Window from kivy.lang import Builder Window.borderless = True def capture_mic_data(): chunk = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 p = pyaudio.PyAudio() s = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=chunk) global levels while True: data = s.read(chunk) mx = audioop.rms(data, 2) if len(levels) >= 100: levels = [] levels.append(mx) class Logic(BoxLayout): def __init__(self, **kwargs): super(Logic, self).__init__(**kwargs) self.plot = MeshLinePlot(color=[1,0,0,1]) def start(self): self.ids.graph.add_plot(self.plot) Clock.schedule_interval(self.get_value, 0.0001) def stop(self): Clock.unschedule(self.get_value) def get_value(self, dt): self.plot.points = [(i, j/5) for i, j in enumerate(levels)] class MainApp(App): def build(self): return Builder.load_file("main.kv") if __name__ == "__main__": levels = [] capture_mic_data_thread = Thread(target=capture_mic_data) capture_mic_data_thread.daemon = True capture_mic_data_thread.start() MainApp().run()
原KV文件代码无需修改,保存为main.kv和Python文件放在同一目录即可正常运行。
内容的提问来源于stack exchange,提问作者PythonRookie
相关产品推荐
相关产品推荐

