使用os.path.walk时出现变量在赋值前引用的问题
好的。我之前有一些Matlab的基础,现在我正在转向Python。我在64位Linux上使用Python 2.6.5写了一段代码,这段代码会浏览目录,找到名为'GeneralData.dat'的文件,从中提取一些数据,并把它们拼接成一个新的数据集:
import pylab as p
import os, re
import linecache as ln
def LoadGenomeMeanSize(arg, dirname, files):
for file in files:
filepath = os.path.join(dirname, file)
if filepath == os.path.join(dirname,'GeneralData.dat'):
data = p.genfromtxt(filepath)
if data[-1,4] != 0.0: # checking if data set is OK
data_chopped = data[1000:-1,:] # removing some of data
Grand_mean = data_chopped[:,2].mean()
Grand_STD = p.sqrt((sum(data_chopped[:,4]*data_chopped[:,3]**2) + sum((data_chopped[:,2]-Grand_mean)**2))/sum(data_chopped[:,4]))
else:
break
if filepath == os.path.join(dirname,'ModelParams.dat'):
l = re.split(" ", ln.getline(filepath, 6))
turb_param = float(l[2])
arg.append((Grand_mean, Grand_STD, turb_param))
GrandMeansData = []
os.path.walk(os.getcwd(), LoadGenomeMeanSize, GrandMeansData)
GrandMeansData = sorted(GrandMeansData, key=lambda data_sort: data_sort[2])
TheMeans = p.zeros((len(GrandMeansData), 3 ))
i = 0
for item in GrandMeansData:
TheMeans[i,0] = item[0]
TheMeans[i,1] = item[1]
TheMeans[i,2] = item[2]
i += 1
print TheMeans # just checking...
# later do some computation on TheMeans in NumPy
然后它给我抛出了这个错误(虽然我发誓一个月前它是正常工作的):
Traceback (most recent call last):
File "/home/User/01_PyScripts/TESTtest.py", line 29, in <module>
os.path.walk(os.getcwd(), LoadGenomeMeanSize, GrandMeansData)
File "/usr/lib/python2.6/posixpath.py", line 233, in walk
walk(name, func, arg)
File "/usr/lib/python2.6/posixpath.py", line 225, in walk
func(arg, top, names)
File "/home/User/01_PyScripts/TESTtest.py", line 26, in LoadGenomeMeanSize
arg.append((Grand_mean, Grand_STD, turb_param))
UnboundLocalError: local variable 'Grand_mean' referenced before assignment
好吧……所以我去查了一些资料,想出了这个全局变量:
import pylab as p
import os, re
import linecache as ln
Grand_mean = p.nan
Grand_STD = p.nan
def LoadGenomeMeanSize(arg, dirname, files):
for file in files:
global Grand_mean
global Grand_STD
filepath = os.path.join(dirname, file)
if filepath == os.path.join(dirname,'GeneralData.dat'):
data = p.genfromtxt(filepath)
if data[-1,4] != 0.0: # checking if data set is OK
data_chopped = data[1000:-1,:] # removing some of data
Grand_mean = data_chopped[:,2].mean()
Grand_STD = p.sqrt((sum(data_chopped[:,4]*data_chopped[:,3]**2) + sum((data_chopped[:,2]-Grand_mean)**2))/sum(data_chopped[:,4]))
else:
break
if filepath == os.path.join(dirname,'ModelParams.dat'):
l = re.split(" ", ln.getline(filepath, 6))
turb_param = float(l[2])
arg.append((Grand_mean, Grand_STD, turb_param))
GrandMeansData = []
os.path.walk(os.getcwd(), LoadGenomeMeanSize, GrandMeansData)
GrandMeansData = sorted(GrandMeansData, key=lambda data_sort: data_sort[2])
TheMeans = p.zeros((len(GrandMeansData), 3 ))
i = 0
for item in GrandMeansData:
TheMeans[i,0] = item[0]
TheMeans[i,1] = item[1]
TheMeans[i,2] = item[2]
i += 1
print TheMeans # just checking...
# later do some computation on TheMeans in NumPy
它没有给我错误信息。甚至还生成了一个包含数据的文件……但是数据完全不对!我通过运行命令手动检查了一些文件:
import pylab as p
data = p.genfromtxt(filepath)
data_chopped = data[1000:-1,:]
Grand_mean = data_chopped[:,2].mean()
Grand_STD = p.sqrt((sum(data_chopped[:,4]*data_chopped[:,3]**2) \
+ sum((data_chopped[:,2]-Grand_mean)**2))/sum(data_chopped[:,4]))
结果它们是不同的 :-(
1) 有没有人能告诉我哪里出错了?
2) 有没有人知道解决办法?
我会非常感激任何帮助 :-)
谢谢,
PTR
3 个回答
我发现你提供的代码和解决方案中有一个问题。
不要通过让变量可见来掩盖“变量在赋值前引用”的问题。 试着理解为什么会发生这种情况。
在你创建全局变量“Grand_mean”之前,你遇到了一个问题,就是在给它赋值之前就试图访问它。在这种情况下,如果你在函数外部初始化这个变量并把它标记为全局变量,这只是掩盖了问题。
你看到错误的结果是因为你让这个变量变得可见了(通过声明为全局变量),但问题依然存在。你的 Grand_mean 从来没有被赋值为正确的数据。
这意味着在“if filepath == os.path.join(dirname,...” 这段代码下的部分从来没有被执行过。
我想说这个条件没有通过:
if filepath == os.path.join(dirname,'GeneralData.dat'):
这意味着你在处理文件的时候,没有先找到 GeneralData.dat 文件再找到 ModelParams.dat 文件。可能你需要按字母顺序排序一下,或者是这个文件根本就不存在。
使用全局变量并不是一个好的解决办法。只有在你确实想要引用和赋值给全局的“Grand_mean”这个名字时,这样做才有意义。需要区分的原因是解释器在函数声明时会预先扫描赋值操作符。
你应该先在LoadGenomeMeanSize()
这个函数的范围内给Grand_mean
赋一个默认值。在一次循环中,你有四个分支可以给Grand_mean赋一个有意义的值。你可能遇到的情况是:
if filepath == os.path.join(dirname,'ModelParams.dat'):
这个条件成立,但要么if filepath == os.path.join(dirname,'GeneralData.dat'):
不成立,要么if data[-1,4] != 0.0:
不成立。很可能是第二个条件没有通过。你需要调整一下代码。
简单来说,你可能需要像这样重新安排你的代码:
...
if filepath == os.path.join(dirname,'GeneralData.dat'):
data = p.genfromtxt(filepath)
if data[-1,4] != 0.0: # checking if data set is OK
data_chopped = data[1000:-1,:] # removing some of data
Grand_mean = data_chopped[:,2].mean()
Grand_STD = p.sqrt((sum(data_chopped[:,4]*data_chopped[:,3]**2) + sum((data_chopped[:,2]-Grand_mean)**2))/sum(data_chopped[:,4]))
if filepath == os.path.join(dirname,'ModelParams.dat'):
l = re.split(" ", ln.getline(filepath, 6))
turb_param = float(l[2])
arg.append((Grand_mean, Grand_STD, turb_param))
else:
break
...