Проблемы с переменной, указанной перед присваиванием при использовании os.path.walk - PullRequest
0 голосов
/ 15 ноября 2010

OK. У меня есть опыт работы с Matlab, и сейчас я перехожу на Python. У меня есть этот фрагмент кода под Pythnon 2.6.5 на 64-битной Linux, который просматривает каталоги, находит файлы с именем '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) Кто-нибудь знает решение этого вопроса?

Буду благодарен за помощь: -)

Cheers, PTR

Ответы [ 3 ]

0 голосов
/ 15 ноября 2010

Я вижу одну проблему с кодом и предоставленным вами решением.

Никогда не скрывайте проблему «ссылки на переменные перед присваиванием», просто делая переменную видимой. Попробуйте понять, почему это произошло?

До создания глобальной переменной "Grand_mean" у вас возникла проблема с доступом к Grand_mean до того, как ей было присвоено какое-либо значение. В таком случае, инициализируя переменную вне функции и помечая ее как глобальную, можно скрыть проблему.

Вы видите ошибочный результат, потому что теперь вы сделали переменную видимой, я сделал ее глобальной, но проблема продолжает существовать. Вы, Grand_mean, никогда не уравнивались с некоторыми правильными данными.

Это означает, что раздел кода в разделе "if filepath == os.path.join (dirname, ...") никогда не выполнялся.

0 голосов
/ 15 ноября 2010

Использование глобальных не является правильным решением. Это имеет смысл, только если вы действительно хотите сослаться и присвоить глобальное имя «Grand_mean». Необходимость устранения неоднозначности возникает из-за того, что интерпретатор предварительно сканирует операторы присваивания в объявлениях функций.

Вы должны начать с присвоения значения по умолчанию Grand_mean в области действия LoadGenomeMeanSize(). У вас есть 1 из 4 ветвей, чтобы фактически присвоить 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

...
0 голосов
/ 15 ноября 2010

Я бы сказал, что это условие не выполняется: if filepath == os.path.join(dirname,'GeneralData.dat'):

, что означает, что вы не получаете GeneralData.dat до ModelParams.dat.Возможно, вам нужно отсортировать по алфавиту или файла там нет.

...