1

私はPythonを初めて使用しますが、痛む問題があります。infile (テキスト) を読み取り、いくつかの値を変更し、outfile (これもテキスト) を書き込むプログラムを受け取りました。出力ファイルが大きくなるにつれて、書き込みはますます遅くなり、2 MB を超えると耐えられないほど遅くなります。なぜこれができるのですか?さまざまなサイズのバッファーを使用するようにコードを変更しようとしましたが、書き込む前にデータをより大きなチャンク (文字列) にキャッシュするように変更しました。+= の代わりに結合して、書き込む文字列を作成することも試みました。これらのいずれもパフォーマンスにまったく違いはありません-より大きなチャンクを書き込むことを除いて、実際にコードが遅くなりました.(!!!)

outfile を書き込むメソッドは次のとおりです。書き込み部分を別のメソッドからインラインに移動しました。

for ifile in _file_stripper(f_in):
    parse_infile(ifile)
    date = variable_data['arkiveringsdatum']
    variable_data['arkiveringsdatum'] = datetime( int(date[0:4]), int(date[4:6]), int(date[6:8]), tzinfo=TZ()).isoformat('T')
    _personnr= variable_data['personnr'].replace('-', '').split(' ')[0]
    tmplist = ['<utskriftsstatus><brevid_kalla>', variable_data['brevid_kalla'], '</brevid_kalla><mapp>Se Allt</mapp><tidpunkt>', variable_data['arkiveringsdatum'], '</tidpunkt><dokumentpaket>', variable_data['dokumenttyp'], '</dokumentpaket><status>Utskriven</status><rensningsdatum>999999</rensningsdatum><kundid_gdb>', variable_data['kundid_gdb'], '</kundid_gdb><personnr>', _personnr, '</personnr></utskriftsstatus>']
    f_out.write(''.join(tmplist))

メソッド_file_stripperは、大きなファイルをレコードに分割します。infiles は 5 ~ 21 MB です。

エラーを探す場所を教えてください。速度低下について言えば、約 1 MB が書き込まれた後、書き込み速度は 4KB 書き込み/秒を下回り、outfile が大きくなるにつれて低下し続けます。

編集: リクエストに応じて、ここに parse_infile と _file_stripper があります:

def parse_infile(f_in):
   index = ""     #variabel som håller vilken ondemandvariabel vi läser in
   found_data = 0  #1 ifall vi hittat det vi letar efter annars 0
   for row in f_in:
      if( 'personnr' in row):
         found_data=1
         index = "personnr"
      elif( 'kundid_gdb' in row):
         found_data=1
         index = "kundid_gdb"
      elif( 'brevid_kalla' in row):
         found_data=1
         index = "brevid_kalla"
      elif( 'arkiveringsdatum' in row):
         found_data=1
         index = "arkiveringsdatum"
      elif( 'GROUP_FILENAME' in row ):
         variable_data['dokumenttyp'] = row.split(':')[-1].split('.')[2].capitalize()
      elif(found_data==1):
         variable_data[index] = row.split(':')[1].strip() 
         index = ""  #Nollställ index ifall värden saknas i filen
         found_data=0
      else:
         pass

def _file_stripper(tot_file):
   try:
      myfile = []
      for rows in tot_file:
         if not 'GROUP_FILENAME' in rows:
            myfile.append(rows)
         else:
            myfile.append(rows)
            yield myfile
   except Exception:
      pass

variable_data = { "brevid_kalla": "", "arkiveringsdatum": "", 
          "kundid_gdb": "", "personnr": "",
          "dokumenttyp": "" }
4

2 に答える 2

1

最も可能性が高いのはvariable_data、解析されたファイルごとに、またはその中のいくつかのフィールドが成長していることです。

あなたのparse_infile 関数はおそらくそれをリセットせず、新しいファイルの値をすでにそこにある値に追加しているため、ファイルを読み取るたびにサイズが大きくなり、説明したように (O² ) で使用されるリソースが発生します。

最善の方法は、グローバル変数に依存しないことです。parse_infile関数が相互作用ごとに新しい辞書を作成し、それを呼び出し元に返すようにします。メイン関数で、関数の戻り値を辞書に割り当てます。

def parse_infile(file_):
    variable_data = {}
    (...)
    return variable_data

(...)
for ifile in _file_stripper(f_in):
    variable_data = parse_infile(ifile)
    (...)
于 2013-01-11T12:04:48.057 に答える
0

あなたの_file_stripper関数は、myfileリストをリセットすることなく、無限にリストに追加されます:

def _file_stripper(tot_file):
   try:
      myfile = []
      for rows in tot_file:
         if not 'GROUP_FILENAME' in rows:
            myfile.append(rows)
         else:
            myfile.append(rows)
            yield myfile
   except Exception:
      pass

myfileはループの外側に設定され、各行は に追加され、そのまま生成されることに注意してくださいmyfile。したがって、プロセスのメモリフットプリントがどんどん大きくなり、最終的にOSがメモリのスワップアウトを開始することを余儀なくされ、プロセスが遅くなります.

に表示されないmyfileときにリセットするつもりだったと思います:GROUP_FILENAMErows

def _file_stripper(tot_file):
   try:
      myfile = []
      for rows in tot_file:
         if not 'GROUP_FILENAME' in rows:
            myfile.append(rows)
         else:
            myfile.append(rows)
            yield myfile
            myfile = []
   except Exception:
      pass
于 2013-01-14T17:10:57.923 に答える