导入numpy模块后调用input()报TypeError问题求助
问题根因
- 报错和numpy导入逻辑无关,核心是你把Python内置的
input函数名当成自定义变量名用了:代码中input = np.sin(2*np.pi*np.arange(fs*duration)*f/fs)这行执行后,input标识符就不再是用来获取用户输入的内置函数,而是指向你生成的numpy音频数组。 - 如果你在Jupyter、IPython这类会保留运行状态的交互环境调试,只要之前运行过上面那行赋值语句,哪怕你把
n = input("Give")写在赋值行前面,重跑代码时内核里的input已经被替换成ndarray对象,调用时必然抛出TypeError: 'numpy.ndarray' object is not callable错误。 - 你想的3种隔离方案都能绕开问题,但完全没必要搞这么复杂,最直接的修复方式就是不要占用内置函数名。
最简修复代码
把占用内置名的变量、函数参数全部改名即可,改完直接运行:
import pyaudio import numpy as np noteslist = {"C":-10,"C#":-9,"D":-8,"D#":-7,"E":-6,"E#":-5,"F":-4,"F#":-3,"G":-2,"G#":-1,"A":0,"A#":1,"B":2} n = input("Give str") fs = 44100 duration = 5.0 f = 432.0 # 原变量名input改为audio_signal,避免覆盖内置函数 audio_signal = np.sin(2*np.pi*np.arange(fs*duration)*f/fs) # 参数名也不要用内置函数名 def play(signal): sample = signal.astype(np.float32) volume = 0.25 p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate=fs, output=True) stream.write(volume*sample) stream.stop_stream() stream.close() p.terminate() play(audio_signal)
交互环境调试的话,改完代码一定要重启内核再运行,重置之前被覆盖的内置
input函数,否则报错不会消失。
你提到的3种思路的实现参考
如果确实需要做逻辑隔离,可按下面方式实现,不需要改内置名也能跑:
- 方案1:拆分独立文件
新建audio_utils.py存放音频相关逻辑,和输入逻辑完全隔离:
主文件只处理输入,需要播放时再导入模块:# audio_utils.py 内容 import pyaudio import numpy as np def play_sine_wave(freq=432.0, sample_rate=44100, duration=5.0, volume=0.25): wave = np.sin(2*np.pi*np.arange(sample_rate*duration)*freq/sample_rate) sample = wave.astype(np.float32) p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate=sample_rate, output=True) stream.write(volume*sample) stream.stop_stream() stream.close() p.terminate()# 主文件内容 noteslist = {"C":-10,"C#":-9,"D":-8,"D#":-7,"E":-6,"E#":-5,"F":-4,"F#":-3,"G":-2,"G#":-1,"A":0,"A#":1,"B":2} n = input("Give str") # 输入全部处理完再导入音频模块 from audio_utils import play_sine_wave play_sine_wave() - 方案2、3:分段隔离/延后导入numpy
把所有需要调用input()获取用户输入的逻辑放在最前面,全部跑完再导入numpy、写音频生成逻辑,避免提前覆盖标识符:# 第一部分:不导入numpy,先处理所有输入 noteslist = {"C":-10,"C#":-9,"D":-8,"D#":-7,"E":-6,"E#":-5,"F":-4,"F#":-3,"G":-2,"G#":-1,"A":0,"A#":1,"B":2} n = input("Give str") fs = 44100 duration = 5.0 f = 432.0 # 第二部分:输入全部获取完成,再导入依赖运行音频逻辑 import pyaudio import numpy as np audio_signal = np.sin(2*np.pi*np.arange(fs*duration)*f/fs) def play(signal): sample = signal.astype(np.float32) volume = 0.25 p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate=fs, output=True) stream.write(volume*sample) stream.stop_stream() stream.close() p.terminate() play(audio_signal)
写Python代码时尽量不要用input、list、dict、str这类内置函数/类名当自定义变量名,这类问题排查起来非常浪费时间。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

