IndexError: размер массива данных не соответствует срезу

Почему я получаю эту ошибку только при последующем выполнении функции Python?

Я запускаю скрипт Python, который преобразует один тип файла netCDF4 в другой и делает это, вызывая функцию в модуле, который я написал.

Скрипт последовательно обрабатывает несколько файлов. Когда я добираюсь до второго файла в списке, я получаю «IndexError: размер массива данных не соответствует срезу» в «данные ['время'] [:]» в этом фрагменте кода в моей функции:

varobj = cdf.createVariable('time','f8',('time'))
varobj.setncatts(dictifyatts(data['time'],''))
varobj[:] = data['time'][:]

Неважно, что это за файл. Скрипт всегда успешно обрабатывал первый файл, а затем давился вторым, например. во второй раз он вызывает функцию, в которой произошел сбой, в первый раз все в порядке.

Используя отладчик, я обнаружил, что нет никакой разницы в varobj[:] и data['time'][:] от первого до второго вызова. Следующее:

Второй раз, когда функция вызывается, проверка переменных показывает:

ipdb> data['time']
<class 'netCDF4._netCDF4.Variable'>
float64 time(time)
    description: time of measurement
    calendar: gregorian
    units: seconds since 1970-01-01T00:00:00 UTC
path = /Data/Burst
unlimited dimensions: 
current shape = (357060,)
filling off


ipdb> varobj
<class 'netCDF4._netCDF4.Variable'>
float64 time(time)
    description: time of measurement
    calendar: gregorian
    units: seconds since 1970-01-01T00:00:00 UTC
unlimited dimensions: 
current shape = (357056,)
filling on, default _FillValue of 9.969209968386869e+36 used

При первом вызове функции проверка переменных показывает точно такой же результат с фигурами одинакового размера.

Об этой же ошибке сообщается здесь: Ошибка при создании переменной для создания файл netCDF

И на основе этого я попробовал следующий код:

cf_time = data['time'][:]
cdf.createVariable('time','f8',('time'))
cdf['time'].setncatts(dictifyatts(data['time'],''))
cdf['time'][:] = cf_time[:]

Что тоже не сработало. Та же ошибка при тех же обстоятельствах.

У меня нет идей, и я мог бы использовать предложения о том, что проверить дальше.

Спасибо, Барт, что подсмотрел изменение формы. Это была большая подсказка. Я проверял имена файлов.

Когда я исследовал изменение формы, я обнаружил, что в моей функции одна из входных переменных содержит информацию из предыдущего вызова функции.
Во-первых, почему только одна из входных переменных может хранить устаревшую информацию?
Во-вторых, этого вообще не должно быть, это должно быть за рамками.

Я попытаюсь воспроизвести это поведение в минимизированном коде, а между тем ответы на вопрос о области действия в python будут оценены — я думал, что понял, как python обрабатывает область действия.

Вот минимальный код, который продемонстрирует проблему. Каким-то образом вызывающая функция может изменить переменную (good_ens), которая находится вне области видимости.

def doFile(infileName, outfileName, goodens, timetype, flen):

    print('infilename = %s' % infileName)
    print('outfilename = %s' % outfileName)
    print('goodens at input are from %d to %d' % (goodens[0],goodens[1]))
    print('timetype is %s' % timetype)

    maxens = flen # fake file length
    print('%s time variable has %d ensembles' % (infileName,maxens))

    # TODO - goodens[1] has the file size from the previous file run when multiple files are processed!
    if goodens[1] < 0:
        goodens[1] = maxens

    print('goodens adjusted for input file length are from %d to %d' % (goodens[0],goodens[1]))

    nens = goodens[1]-goodens[0]
    print('creating new netCDF file %s with %d records (should match input file)' % (outfileName, nens))



datapath = ""

datafiles = ['file0.nc',\
             'file1.nc',\
             'file2.nc',\
             'file3.nc']
# fake file lengths for this demonstration
datalengths = [357056, 357086, 357060, 199866]
outfileroot = 'outfile'
attFile = datapath + 'attfile.txt'
# this gets changed!  It should never be changed!
# ask for all ensembles in the file
good_ens = [0,-1]

 # --------------  beyond here the user should not need to change things
for filenum in range(len(datafiles)):

    print('\n--------------\n')
    print('Input Parameters before function call')
    print(good_ens)
    inputFile = datapath + datafiles[filenum]
    print(inputFile)
    l = datalengths[filenum]
    print(l)
    outputFile = datapath + ('%s%03d.cdf' % (outfileroot,filenum))
    print(outputFile)

    print('Converting from %s to %s' % (inputFile,outputFile))
    # the variable good_ens gets changed by this calling function, and should not be
    doFile(inputFile, outputFile, good_ens, 'CF', l)
    # this works, but will not work for me in using this function
    #doNortekRawFile(inputFile, outputFile, [0,-1], 'CF', l)

person Marinna Martini    schedule 01.09.2017    source источник
comment
Я могу подтвердить, что это происходит на двух разных установках anaconda python, conda 4.2.13 и 4.3.22.   -  person Marinna Martini    schedule 01.09.2017
comment
Странная проблема; Я вижу, что форма меняется, но это не должно быть проблемой с неограниченным размером. Можете ли вы воспроизвести проблему на минимальном рабочем примере? Это облегчает другим попытку отладки этой проблемы.   -  person Bart    schedule 01.09.2017
comment
Спасибо, что увидели изменение формы - я думал, что это не так. Возможно, это так.   -  person Marinna Martini    schedule 01.09.2017


Ответы (2)


Я пришел сюда, потому что у меня была такая же ошибка при попытке поместить большой xarray в файл netcdf. Оказывается, мне пришлось повторно разбить набор данных на однородные куски без остатков. Dask делает это с помощью «compute_chunk_sizes()», в xarray вы можете указать куски с помощью «arr.chunk()». документация xarray .chunk()

person benschbob91    schedule 13.01.2020

Итак, проблема здесь возникла из-за того, что старый программист C (я) неправильно понял, как python передает объекты функциям. Я сократил код, изолировал проблему и разместил ее здесь: содержимое переменной python изменяется функцией, когда никаких изменений не предполагается Где был дан ответ: python всегда передает указатели, в отличие от C, который явно указывает, передается ли указатель или содержимое.

person Marinna Martini    schedule 06.09.2017