web-dev-qa-db-ja.com

ファイルとループの混合

別のプログラムからのエラーをログに記録し、エラーが発生したときに中断したプログラムを再起動するスクリプトを書いています。何らかの理由で、このプログラムの開発者は、デフォルトでこの機能をプログラムに組み込む必要がないと感じていました。

とにかく、プログラムは入力ファイルを受け取り、それを解析して、出力ファイルを作成します。入力ファイルは特定の形式です。

UI - 26474845
TI - the title (can be any number of lines)
AB - the abstract (can also be any number of lines)

プログラムがエラーをスローすると、エラーを追跡するために必要な参照情報、つまり、UI、セクション(タイトルまたは要約)、およびタイトルまたは要約の先頭からの相対的な行番号が提供されます。参照番号とファイルを取得し、文を見つけてログに記録する関数を使用して、入力ファイルから問題のある文をログに記録したいと思います。私がそれを行うと考えることができる最良の方法は、ファイルを特定の回数(つまり、n回、ここでnはセクションの先頭に対する行番号です)前進することです。これを行うのが理にかなっていると思われる方法は次のとおりです。

i = 1
while i <= lineNumber:
    print original.readline()
    i += 1

これがどのようにしてデータを失うのかわかりませんが、Pythonはそれがそうであると考え、ValueError: Mixing iteration and read methods would lose data。誰かがこれを正しく行う方法を知っていますか?

27
Allan Lavell

コードにはおそらくoriginal.readline()に加えてfor line in original:があるため、ValueErrorが発生します。プログラムを遅くしたり、より多くのメモリを消費したりせずに問題を修正する簡単なソリューションが変更されています

for line in original:
    ...

while True:
    line = original.readline()
    if not line: break
    ...
49
pts

forおよび enumerate を使用します。

例:

for line_num, line in enumerate(file):
    if line_num < cut_off:
        print line

[〜#〜]注[〜#〜]:これは、ファイルハンドルなどを既にクリーンアップしていることを前提としています。

また、 takewhile 関数は、より機能的なフレーバーを好む場合に役立つことがあります。

12
Hank Gay

必要な行が1行だけだとすると、これは役に立ちます。

import itertools

def getline(fobj, line_no):
    "Return a (1-based) line from a file object"
    return itertools.islice(fobj, line_no-1, line_no).next() # 1-based!

>>> print getline(open("/etc/passwd", "r"), 4)
'adm:x:3:4:adm:/var/adm:/bin/false\n'

StopIterationエラーをキャッチしたい場合があります(ファイルの行数が少ない場合)。

0
tzot

醜いものがないバージョンですwhile Trueパターンおよび他のモジュールなし:

for line in iter(original.readline, ''):
    if …:   # to the beginning of the title or abstract
        for i in range(lineNumber):
            print original.readline(),
        break
0
Armali