特定の行のみを読み取る


回答:


253

読み取るファイルが大きく、メモリ内のファイル全体を一度に読み取りたくない場合:

fp = open("file")
for i, line in enumerate(fp):
    if i == 25:
        # 26th line
    elif i == 29:
        # 30th line
    elif i > 29:
        break
fp.close()

th行i == n-1については注意してくださいn


Python 2.6以降の場合:

with open("file") as fp:
    for i, line in enumerate(fp):
        if i == 25:
            # 26th line
        elif i == 29:
            # 30th line
        elif i > 29:
            break

8
enumerate(x)はを使用するx.nextため、メモリ内のファイル全体を必要としません。
Alok Singhal、2010年

3
これを使った私の小さな牛肉は、A)オープン/クローズのペアの代わりに使用して、体を短く保ちたいです。B)体はそれほど短くありません。速度/スペースとPythonicの間のトレードオフのように聞こえます。最善の解決策は何なのかわかりません。
Hamish Grubijan、2010年

5
過大評価されているため、Pythonはそれなしで13年間以上うまく機能しています
Dan D.

38
@Dan D.電気は過大評価されており、人類はそれなしで20万年以上も問題なく暮らしてきました。;-) 'with'は、より安全で読みやすくなり、1行短くなります。
Romain Vincent

9
forループを使用する理由、私はあなたがの意味を理解していないと思いますbig file。ループがインデックスに到達するまで数
かかる

159

簡単な答え:

f=open('filename')
lines=f.readlines()
print lines[25]
print lines[29]

または:

lines=[25, 29]
i=0
f=open('filename')
for line in f:
    if i in lines:
        print i
    i+=1

多くの行を抽出するためのよりエレガントなソリューションがあります:linecache「python:巨大なテキストファイルの特定の行にジャンプする方法」の礼儀?)、以前のstackoverflow.comの質問の)。

上記でリンクされたpythonのドキュメントを引用:

>>> import linecache
>>> linecache.getline('/etc/passwd', 4)
'sys:x:3:3:sys:/dev:/bin/sh\n'

変更 4目的の行番号にすれば完了です。カウントはゼロベースなので、4は5行目をもたらすことに注意してください。

ファイルが非常に大きく、メモリに読み込むときに問題が発生する可能性がある場合は、@ Alokの助言を得てenumerate()を使用することをお勧めします。

結論として:

  • fileobject.readlines()またはfor line in fileobjectを使用して、小さなファイルをすばやく解決します。
  • linecacheより洗練されたソリューションに使用します。これは、繰り返し可能である多くのファイルの読み取りに非常に高速です。
  • テイクAlokのアドバイスや使用@enumerate()非常に大きくなる可能性があるファイルの場合、およびメモリに収まらないだろう。ファイルが順次読み取られるため、この方法を使用すると速度が低下する可能性があることに注意してください。

7
いいね。linecacheモジュールのソースを確認したところ、メモリ内のファイル全体を読み取っているようです。したがって、ランダムアクセスがサイズの最適化よりも重要な場合linecacheは、これが最善の方法です。
Alok Singhal、2010年

7
with linecache.getlin( 'some_file'、4)5行目ではなく4行目を取得します。
フアン

面白い事実:2番目の例のリストの代わりにセットを使用すると、O(1)の実行時間になります。リストで調べるのはO(n)です。内部的にセットはハッシュとして表されます。そのため、O(1)の実行時間が得られます。この例では大したことではありませんが、数値の大きなリストを使用し、効率を重視する場合は、セットが適しています。
rady

linecache現在、Pythonソースファイルでのみ機能するように見えます
Paul H

またlinecache.getlines('/etc/passwd')[0:4]、1行目、2行目、3行目、4行目の読み取りにも使用できます。
zyy

30

高速でコンパクトなアプローチは次のとおりです。

def picklines(thefile, whatlines):
  return [x for i, x in enumerate(thefile) if i in whatlines]

これは、開いているファイルのようなオブジェクトthefile(ディスクファイルから開くか、ソケットやその他のファイルのようなストリームを介して開くかを呼び出し元に任せる)とゼロベースのラインインデックスのセットを受け入れwhatlines、メモリフットプリントが低く、速度が妥当なリスト。返される行数が膨大な場合は、ジェネレータを使用することをお勧めします。

def yieldlines(thefile, whatlines):
  return (x for i, x in enumerate(thefile) if i in whatlines)

これは基本的にループするのにのみ適しています-唯一の違いは、 returnステートメントでそれぞれリスト内包表記とジェネレータ式を作成することです。

「行」の言及と「ファイル」もかかわらず、これらの機能は、多くのしていることにも注意するくらい、彼らは上で動作します-より一般的な任意の項目の反復可能な、それはリスト(または発電機)を返す、開いているファイルやその他のことそれらの進歩的なアイテム番号に基づいています。したがって、より適切な一般的な名前を使用することをお勧めします;-)。


@ephemient、私は同意しません-genexpはスムーズかつ完全に読み取ります。
Alex Martelli、2010年

優秀でエレガントなソリューション、ありがとう!実際、ジェネレータ式を使用すると、大きなファイルでもサポートする必要があります。これ以上に優雅になりませんか?:)
サミュエルランパ2014

素晴らしい解決策、これは@AdamMatanによって提案されたものとどのように比較されますか Adamソリューションは、早期停止につながる可能性がある追加情報(行番号が単調に増加する)を利用するため、より高速になる可能性があります。メモリに読み込めない10GBのファイルがあります。
Mannaggia 2014年

2
@Mannaggiaこの回答では十分に強調されていwhatlinesませんが、(ソートされた)リストではなくセットを使用すると高速に実行されるためset、である必要がありif i in whatlinesます。私は最初にそれに気づかず、代わりにソートされたリストを使用して独自の醜い解決策を考案しました(毎回リストをスキャンする必要はありませんでしたがif i in whatlines、それだけです)が、パフォーマンスの違いはごくわずか(私のデータでは)で、これソリューションははるかにエレガントです。
ビクターK

28

別のソリューションを提供するために:

import linecache
linecache.getline('Sample.txt', Number_of_Line)

これが迅速かつ簡単であることを願っています:)


1
これが最も最適なソリューションであることを願っています。
maniac_user 2013年

2
これにより、ファイル全体がメモリに読み込まれます。file.read()。split( '\ n')を呼び出してから、配列インデックスルックアップを使用して対象の行を取得することもできます...
duhaime

あなたは、例えば@duhaime提供することができます
アノン

14

7行目が必要な場合

line = open( "file.txt"、 "r")。readlines()[7]

14
きちんと。しかしclose()、この方法でファイルを開くと、ファイルはどうなりますか?
Milo Wielondek、2011年

1
@ 0sh私たちは閉じる必要がありますか?
Ooker

1
はい。この後に閉じる必要があります。「with」を使用してファイルを開くと、ファイル自体が閉じます。
reetesh11

10

完全を期すために、もう1つのオプションがあります。

python docsの定義から始めましょう。

スライス通常、シーケンスの一部を含むオブジェクト。スライスは、添字表記[]を使用して作成されます。variable_name[1:3:5]のように、いくつかの数値が指定されている場合は、数値の間にコロンが付きます。ブラケット(添え字)表記は内部でスライスオブジェクトを使用します(または古いバージョンでは、__ getslice __()および__setslice __())。

スライス表記は一般的にイテレータに直接適用できませんが、itertoolsパッケージには置換関数が含まれています。

from itertools import islice

# print the 100th line
with open('the_file') as lines:
    for line in islice(lines, 99, 100):
        print line

# print each third line until 100
with open('the_file') as lines:
    for line in islice(lines, 0, 100, 3):
        print line

この関数の追加の利点は、最後までイテレーターを読み取らないことです。したがって、より複雑なことができます。

with open('the_file') as lines:
    # print the first 100 lines
    for line in islice(lines, 100):
        print line

    # then skip the next 5
    for line in islice(lines, 5):
        pass

    # print the rest
    for line in lines:
        print line

そして元の質問に答えるには:

# how to read lines #26 and #30
In [365]: list(islice(xrange(1,100), 25, 30, 4))
Out[365]: [26, 30]

1
大きなファイルを扱う場合は、これが最善のアプローチです。私のプログラムは8GB +を消費することから、ほとんど何もしなくなりました。tradoffはCPU使用率が15%から40%でしたが、ファイルの実際の処理は70%高速でした。私はそのtradoffを一日中取ります。ありがとうございます!🎉🎉🎉
GollyJer

1
これは私にとって最もパイソンのようです。ありがとう!
ipetrik

10

ファイルの読み込みは信じられないほど高速です。100MBのファイルを読み取るのにかかる時間は0.1秒未満です(私の記事「Pythonでのファイルの読み取りと書き込み」を参照してください))。したがって、完全に読んでから、1行で作業する必要があります。

ここでほとんどの答えは間違っていませんが、悪いスタイルです。ファイルをwith再度閉じるには、ファイルを開くときに必ずを使用する必要があります。

したがって、次のようにする必要があります。

with open("path/to/file.txt") as f:
    lines = f.readlines()
print(lines[26])  # or whatever you want to do with this line
print(lines[30])  # or whatever you want to do with this line

巨大なファイル

巨大なファイルがあり、メモリの消費が懸念される場合は、1行ずつ処理できます。

with open("path/to/file.txt") as f:
    for i, line in enumerate(f):
        pass  # process line i

IMO不明な長さのファイル全体を読み取るのは本当に悪いスタイルです。最初の30行を取得するためだけです。
リターン42 '30

@ return42アプリケーションに大きく依存します。多くの場合、テキストファイルのサイズが使用可能なメモリよりもはるかに小さいと想定してもまったく問題ありません。巨大なファイルが存在する可能性がある場合は、私の回答を編集しました。
Martin Thoma

加えてくれてありがとう、alok answerと同じです。申し訳ありませんが、これはアプリケーションに依存するとは思いません。IMOそれはあなたが必要とするより多くの行を読まない方が常に良いです。
return42 '10 / 10/04

7

これらのいくつかは美しいですが、もっと簡単に行うことができます:

start = 0 # some starting index
end = 5000 # some ending index
filename = 'test.txt' # some file we want to use

with open(filename) as fh:
    data = fin.readlines()[start:end]

print(data)

それは単にリストスライスを使用し、ファイル全体をロードしますが、ほとんどのシステムはメモリ使用量を適切に最小化し、上記のほとんどの方法よりも高速で、私の10G +データファイルで機能します。幸運を!


4

あなたはseek()を行うことができます読み取りヘッドをファイル内の指定されたバイトに配置呼び出しを実行できます。読みたい行の前にファイルに書き込まれたバイト(文字)の数が正確にわからない場合、これは役に立ちません。おそらく、ファイルは厳密にフォーマットされています(各行はXバイト数ですか?)、または本当に速度を向上させたい場合は、自分で文字数を数えることができます(改行などの非表示の文字を含めることを忘れないでください)。

それ以外の場合は、ここですでに提案されている多くのソリューションの1つに従って、希望する行の前にすべての行を読み取る必要があります。


3

大きなテキストファイルfileが厳密に構造化されている場合(つまり、すべての行が同じ長さlである場合)、n-th lineに使用できます

with open(file) as f:
    f.seek(n*l)
    line = f.readline() 
    last_pos = f.tell()

免責事項これは同じ長さのファイルに対してのみ機能します!



2

インポートを気にしない場合、fileinputは必要な機能を正確に実行します(これにより、現在の行の行番号を読み取ることができます)。


2
def getitems(iterable, items):
  items = list(items) # get a list from any iterable and make our own copy
                      # since we modify it
  if items:
    items.sort()
    for n, v in enumerate(iterable):
      if n == items[0]:
        yield v
        items.pop(0)
        if not items:
          break

print list(getitems(open("/usr/share/dict/words"), [25, 29]))
# ['Abelson\n', 'Abernathy\n']
# note that index 25 is the 26th item

私の好きな男、ロジャー!これはwithステートメントから利益を得る可能性があります。
Hamish Grubijan、2010年

2

このアプローチの方が汎用的です。つまり、ファイル、オブジェクトの結果f.readlines()StringIOオブジェクトなどで使用できます。

def read_specific_lines(file, lines_to_read):
   """file is any iterable; lines_to_read is an iterable containing int values"""
   lines = set(lines_to_read)
   last = max(lines)
   for n, line in enumerate(file):
      if n + 1 in lines:
          yield line
      if n + 1 > last:
          return

>>> with open(r'c:\temp\words.txt') as f:
        [s for s in read_specific_lines(f, [1, 2, 3, 1000])]
['A\n', 'a\n', 'aa\n', 'accordant\n']

2

ここに、私の小さな2セントがあります。

def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
    fp   = open(filename, "r")
    src  = fp.readlines()
    data = [(index, line) for index, line in enumerate(src) if index in lines]
    fp.close()
    return data


# Usage below
filename = "C:\\Your\\Path\\And\\Filename.txt"
for line in indexLines(filename): # using default list, specify your own list of lines otherwise
    print "Line: %s\nData: %s\n" % (line[0], line[1])

2

Alok Singhalの回答のより良いマイナーな変更

fp = open("file")
for i, line in enumerate(fp,1):
    if i == 26:
        # 26th line
    elif i == 30:
        # 30th line
    elif i > 30:
        break
fp.close()


1

@OP、列挙を使用できます

for n,line in enumerate(open("file")):
    if n+1 in [26,30]: # or n in [25,29] 
       print line.rstrip()

1
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
    print f.readlines()[26]
    print f.readlines()[30]

withステートメントを使用して、ファイルを開き、26行目と30行目を出力してから、ファイルを閉じます。シンプル!


これは有効な答えではありません。readlines()イテレータへの最初の呼び出しが終了し、2番目の呼び出しが空のリストを返すか、エラーをスローした後(どちらか覚えていない)
Paul H

1

これは、誰かが既に述べたこの構文を使用して非常に簡単に行うことができますが、これは、はるかに簡単な方法です。

inputFile = open("lineNumbers.txt", "r")
lines = inputFile.readlines()
print (lines[0])
print (lines[2])

1

行#3を印刷するには

line_number = 3

with open(filename,"r") as file:
current_line = 1
for line in file:
    if current_line == line_number:
        print(file.readline())
        break
    current_line += 1

原作者:フランク・ホフマン


1

かなり迅速かつ要領を得ています。

テキストファイルの特定の行を印刷します。「lines2print」リストを作成し、列挙がlines2printリストの「中に」あるときに印刷します。余分な '\ n'を取り除くには、line.strip()またはline.strip( '\ n')を使用します。私は「リスト内包表記」が好きで、できる限り使用しようとします。何らかの理由でファイルを開いたままにしないようにするために、テキストファイルを読み取る「with」メソッドが好きです。

lines2print = [26,30] # can be a big list and order doesn't matter.

with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in lines2print]

または、リストが小さい場合は、理解度のリストとしてリストに入力するだけです。

with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in [26,30]]

0

目的の行を印刷します。必要な行の上/下の行を印刷します。

def dline(file,no,add_sub=0):
    tf=open(file)
    for sno,line in enumerate(tf):
        if sno==no-1+add_sub:
         print(line)
    tf.close()

execute ----> dline( "D:\ dummy.txt"、6)ie dline( "file path"、line_number、検索した行の上の行が下の-1に1を与える場合、これはオプションのデフォルト値です。とられる0)


0

特定の行を読みたい場合は、次のコードを使用できます。 file = open("files.txt","r") lines = file.readlines() ## convert to list of lines datas = lines[11:] ## raed the specific lines


-1
f = open(filename, 'r')
totalLines = len(f.readlines())
f.close()
f = open(filename, 'r')

lineno = 1
while lineno < totalLines:
    line = f.readline()

    if lineno == 26:
        doLine26Commmand(line)

    elif lineno == 30:
        doLine30Commmand(line)

    lineno += 1
f.close()

7
これは非常に非Pythonicです。
SilentGhost

readlineやreadlineをそのように使用することはできません(それぞれが現在の読み取り位置を変更するため)。

最初のコードで大きなエラーを見落として申し訳ありませんでした。エラーは修正され、現在のコードは期待どおりに動作するはずです。私のエラーを指摘してくれてありがとう、ロジャー・ペイト。
inspectorG4dget

-1

これはうまくいくと思います

 open_file1 = open("E:\\test.txt",'r')
 read_it1 = open_file1.read()
 myline1 = []
 for line1 in read_it1.splitlines():
 myline1.append(line1)
 print myline1[0]

あなたがこれを投稿したとき、すでにダースのreadlineメソッドがありました-別のものを追加するだけで混乱を追加します
duhaime
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.