Python语音助手循环导入ImportError问题修复咨询
问题描述
我正在用Python开发语音助手,这是第一次把代码拆分到不同文件夹/子文件夹中,调用助手时持续出现循环导入错误,报错信息如下:
from src.core.voice_assistant import assistant ImportError: cannot import name 'assistant' from partially initialized module 'src.core.voice_assistant' (most likely due to a circular import) (/Users/tristan/Desktop/Programming/IntelliVoiceAI/src/core/voice_assistant.py)
文件目录结构大致为:
- 项目根目录
- main.py
- src/
- core/
- voice_assistant.py
- core/
相关代码
main.py
from src.core.voice_assistant import VoiceAssistant if __name__ == "__main__": assistant = VoiceAssistant() assistant.run()
voice_assistant.py
import openai import sounddevice as sd import numpy as np import tempfile from scipy.io import wavfile from gtts import gTTS import subprocess class VoiceAssistant: def __init__(self): # 设置OpenAI API密钥 openai.api_key = "api_key_here" # 初始化助手对话历史 self.history = [ { "role": "system", "content": "You are a helpful assistant. The user is english. Only speak english.", } ] def listen(self): """录制用户音频并转写文本""" print("Listening...") # 录制音频 duration = 3 # 录制3秒 fs = 44100 # 采样率 audio = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype=np.int16) sd.wait() # 将NumPy数组保存为临时wav文件 with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_wav_file: wavfile.write(temp_wav_file.name, fs, audio) # 使用临时wav文件调用OpenAI API transcript = openai.Audio.transcribe("whisper-1", temp_wav_file) print(f"User: {transcript['text']}") return transcript["text"] def think(self, text): """根据用户输入生成响应""" # 将用户输入添加到对话历史 self.history.append({"role": "user", "content": text}) # 向GPT API发送对话请求 response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=self.history, temperature=0.5 ) # 从API响应中提取助手回复 message = dict(response.choices[0])["message"]["content"] self.history.append({"role": "system", "content": message}) print("Assistant: ", message) return message def speak(self, text): # 使用gTTS将文本转为语音 tts = gTTS(text=text, lang='en') # 将语音保存为临时音频文件 with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio: tts.save(temp_audio.name) # 通过扬声器播放音频文件 subprocess.run(["afplay", temp_audio.name])
修复方案
从报错信息和现有代码分析,核心问题是模块间出现了互相导入的依赖关系,另外还存在导入名称错误的问题,以下是具体修复步骤:
修正导入名称错误
报错信息显示有代码尝试导入assistant,但你的voice_assistant.py中只有VoiceAssistant类,没有名为assistant的实例对象。检查所有文件的导入语句,确保导入的是正确的类名VoiceAssistant,而非实例名。排查循环依赖关系
遍历src目录下所有文件,找出是否存在如下情况:voice_assistant.py导入了某个子模块(比如拆分出的音频处理模块)- 该子模块又反向导入
voice_assistant.py中的VoiceAssistant类
这种双向导入会触发循环导入错误。
延迟导入(局部导入)
如果确实需要双向依赖,将导入语句从文件顶部移到函数内部,避免模块加载时的互相阻塞。例如:# 在voice_assistant.py的方法内导入依赖模块 def listen(self): from src.core.audio_utils import process_audio # 后续业务代码重构代码解耦
将共享的工具逻辑提取到独立模块中,比如新建src/utils/audio_utils.py存放音频录制/转写工具,src/utils/openai_utils.py存放API调用逻辑,让voice_assistant.py和其他模块都只导入这些工具模块,彻底消除循环依赖。补充缺失的方法
你的voice_assistant.py中缺少run()方法,但main.py里调用了assistant.run(),需要补充该方法才能正常运行:def run(self): """语音助手主循环""" while True: user_input = self.listen() response = self.think(user_input) self.speak(response)
内容的提问来源于stack exchange,提问作者Tristan N

