我的函数抛出了local variable 'pt' referenced before assignment
错误:
Traceback (most recent call last):
File "/home/solesschong/Workspace/PenPal/python/main.py", line 126, in callback
ind = (i+pt) % n
UnboundLocalError: local variable 'pt' referenced before assignment
代码如下
def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
for i in range(frame_count):
ind = (i+pt) % n
return (a, b)
return callback
在全球范围内,
pt = 0
stream = p.open(stream_callback=get_audio_callback(pt))
我无法弄清楚错误发生的原因,因为我已经检查了一些关闭的例子,但没有发现任何区别。
你无法重现错误的原因可能是由于过度简化,正如@Martijn Pieters所提到的那样。 因此原始代码。
此外,我通过引用传递来解决这个问题,请参阅我自己的答案。
"""
Sound API
"""
def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt = pt + frame_count
return (encode(wave), pyaudio.paContinue)
return callback
p = pyaudio.PyAudio()
pt = 0
stream = p.open(format=pyaudio.paFloat32,
channels=2,
rate=RATE,
output=True,
stream_callback=get_audio_callback(pt))
答案 0 :(得分:2)
您的代码分配给pt
中的callback
; Python在编译时确定名称的范围,赋值使其成为本地名称。
pt = pt + frame_count
除非你告诉Python,否则就是这样。在Python 2中,您只能将名称明确标记为global
,而您需要Python 3才能使用nonlocal
关键字:
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
nonlocal pt
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt = pt + frame_count
return (encode(wave), pyaudio.paContinue)
使用nonlocal pt
行明确告知Python不要将pt
视为本地名称,而是将其从get_audio_callback
的封闭范围中删除。
在Python 2中,您可以创建一个从闭包中获取其值的本地:
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
pt_local = pt
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt_local) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt_local = pt_local + frame_count
return (encode(wave), pyaudio.paContinue)
因为封闭的get_audio_callback
范围似乎无法使用pt
,因此无需访问更新的pt_local
值。
如果您确实需要在pt
范围内get_audio_callback
进行更新(例如,callback
被多次调用,您需要pt
从呼叫更新到pt
(请致电),您需要完全避免在callback
功能中使用callback
作为本地。
一个有效的解决方法是将值包装在一个可变对象中,或者将它作为一个可变属性分配给封闭范围和本地范围都可以访问它,而不会被视为本地赋值。在def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+callback.pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
callback.pt = callback.pt + frame_count
return (encode(wave), pyaudio.paContinue)
callback.pt = pt
return callback
函数上设置属性是一种很好的方法:
callback.pt
此处callback
不再是本地名称;它是{{1}}函数对象的一个属性。
答案 1 :(得分:0)
原来是'参考'的问题
我将我的代码更改为按变量传递pt
,结果很好。
pt = [0]
def get_audio_callback(pt_ref):
def callback(in_data, frame_count, time_info, status):
pt = pt_ref[0]
for i in range(frame_count):
ind = (i+pt) % n
return (a, b)
return callback