0

Python 関数の後続の実行時にのみこのエラーが発生するのはなぜですか?

ある種類の netCDF4 ファイルを別の種類に変換する python スクリプトを実行しています。これは、作成したモジュール内の関数を呼び出すことによって実行されます。

スクリプトは複数のファイルを順番に処理します。リストの 2 番目のファイルに到達すると、関数の次のコードの "data['time'][:]" で "IndexError: size of data array does not conform to slice" が表示されます。

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

ファイルが何であるかは関係ありません。スクリプトは常に最初のファイルを問題なく処理し、次に 2 番目のファイルを停止します。たとえば、関数を 2 回呼び出すと失敗しますが、1 回目は問題ありません。

デバッガーを使用して、varobj[:] と data['time'][:] に最初の呼び出しから 2 番目の呼び出しまで違いがないことを発見しました。次のように:

関数が 2 回目に呼び出され、変数を調べると、次のことがわかります。

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[:]

どちらも機能しませんでした。同じ状況で同じエラー。

私はアイデアがありません。次に何を確認するかについての提案を使用できます。

形状の変化をスパイしてくれた Bart に感謝します。それが大きなヒントでした。ファイル名をチェックしていました。

形状の変化を調べたところ、関数内で、入力変数の 1 つが前回関数が呼び出されたときの情報を保持していることがわかりました。
まず、入力変数の 1 つだけが古い情報を保持しているのはなぜでしょうか?
第二に、これはまったく起こらないはずであり、範囲外であるべきです.

最小化されたコードでこの動作を再現しようとしますが、それまでの間、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)
4

2 に答える 2