0

よろしくお願いします。

私はPythonが初めてで、ファイルをある形式から別の形式に変換しようとしています。

ここに私が持っているコードがあります:

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        if line and line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            fnew.write(data[0])
        if not line:  break

print('end of program')
fs.close
fnew.close

ファイルの基本的な形式には、先頭にコメント付きのヘッダーがあり、その後にデータ行が続きます。

私が抱えている問題は、 fnew.write(data[0]) 行にあります。次のエラーが表示されます。

IndexError: リスト インデックスが範囲外です

行の分割により、8 つの列のデータが分割されます。そのうちの最初の 2 つを削除します。したがって、最終的には、ファイル全体から最初の 2 列を除いて書き直す必要があります。もっと複雑な再フォーマットを行う必要がありますが、このステップのエラーを理解できれば、残りの方法を理解できるかもしれません。

- - - - - - - アップデート

abarnet さん、その通りです。エラーの原因は改行です。ただし、あなたが言ったように、チェックを追加しようとすると別の問題が発生します。以下のコードを実行すると、すべてがフリーズします。「if data:」チェックを削除すると実行されますが、同じ「index out of range」エラーが表示されます。

また、「if data:」チェックを削除し、改行を含まないサンプルデータファイルを使用して、以下のように実行しようとしましたが、フリーズしました。

これを引き起こしている可能性のあるものについて誰かが光を当てることができますか?

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        for line in f:
            if line[0]=='#':
                print(line)
                fnew.write(line + '\n')
            else:
                data=line.split()
                if data:
                    print(data[0])
                    fnew.write(data[0] + '\n')

print('end of program')
fs.close
fnew.close

-------------- 更新 2

以下のこのコードは機能します。無限ループの問題を明らかにしてくれた abarnet に感謝します。私が抱えている最後の問題は、改行であろうとヘッダー行であろうと、データの最初の行が無視され、出力に出力されないことです。

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    line = f.readline()
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')
fnew.close()
4

1 に答える 1

1

lineまず、が空の場合はどうなるでしょうか。

最終的に に到達しますif not line: break。しかし、そこにたどり着く前に、最初にたどり着くでしょうelse:(なぜなら、それは真実ではないからですline and line[0]=='#')。だから、あなたのdata = line.split()意志はあなたに与えますdata = []。そして、data[0]を上げますIndexError

if not line: break最初にテストを移動するだけです:

while True:
    line = f.readline()
    if not line:
        break
    elif line[0]=='#':
        print(line)
        fnew.write(line + '\n')
    else:
        data=line.split()
        fnew.write(data[0])

そうは言っても、そもそもこれを書くためのはるかに簡単な方法があります。whileファイルをループすると、ループ アラウンドのように各行が 1 つずつ表示されますreadlineが、EOF に到達するとループは自動的に終了し、何もテストする必要はありませんbreak

for line in f:
    if line[0]=='#':
        print(line)
        fnew.write(line + '\n')
    else:
        data=line.split()
        fnew.write(data[0])

しかし、その行空でない場合、単に空白である場合、または純粋な空白である場合はどうなるでしょうか? たとえば、 を呼び出すsplit()とどうなります' \n'か? 繰り返しますが、空のリストが得られます。したがって、それが可能であれば、同じ問題が再び発生することになります。もちろん、breakそのような場合は、おそらくやりたくありません。何をしたいのかわかりませんが、空白のリンクをスキップしたいとしましょう。elseしたがって、ブロックを次のように置き換えます。

data=line.split()
if data:
    fnew.write(data[0])

fnew.write(line + '\n')補足として、最初のケースでは、行がすでに a で終わっている\nので、余分な改行を追加するのはかなり奇妙ですがfnew.write(data[0])、他のケースでdata[0]は、改行で終わっていないので、一連の最初の列を 1 つの巨大な単語に結合し、次のコメントを末尾に追加するだけです…</p>


新しいコードの問題は、ループをループに置き換えるのではなく、両方を持っていることです。while True:readline()for line in f:

したがって、最初のwhileループでは、最初の行を読み取り、次にファイル内のすべての行を読み取り、終了します。次に、whileループの 2 回目で、最後に残っていないものを読み取り、残りの 0 行をすべて読み取り、終了します。そして、それは永遠に続き、時間の終わりまで最後の 0 行を何度も読み続けbreakますwhile True:

更新されたコードには、他にもいくつかの問題があります。

  • fs.closeメソッドを実際に呼び出すことなく参照するだけです。のように、呼び出しには括弧が必要ですfs.close()
  • fs.close()しかし、とにかくしたくありません。そのwithステートメントの要点は、ファイルを自動的に閉じることです。
  • withおそらくステートメント forも使用したいと思うでしょうfnew

そう:

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')
于 2014-12-05T22:25:41.387 に答える