web-dev-qa-db-ja.com

特定の行だけを読む

ファイルの読み込みにforループを使用していますが、26行目と30行目のように特定の行だけを読みたいと思います。これを実現するための組み込み機能はありますか?

ありがとう

179
3zzy

読み込むファイルが大きい場合、一度にメモリ内のファイル全体を読みたくない場合は、

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()

n行目のi == n-1に注意してください。


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
229
Alok Singhal

簡単な答え:

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を希望の行番号に変更してください。カウントが0から始まるため、4は5行目になります。

ファイルが非常に大きくなり、メモリに読み込まれたときに問題が発生する可能性がある場合は、 @ Alokのアドバイスに従ってenumerate()を使用することをお勧めします

最後まで:

  • 小さなファイルのための迅速な解決策としてfileobject.readlines()またはfor line in fileobjectを使用してください。
  • より洗練された解決策としてlinecacheを使用してください。これは多くのファイルを読むのに非常に速く、繰り返し可能です。
  • 非常に大きくなる可能性があり、メモリに収まらないファイルには @ Alokのアドバイスを参考にしてenumerate() を使用してください。ファイルが順次読み込まれるため、この方法を使用すると遅くなることがあります。
134
Adam Matan

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

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ステートメントで四角括弧ではなく丸括弧を使用して、それぞれリストの内包表記とジェネレーター式を作成することです。

さらに、「行」と「ファイル」に言及しているにもかかわらず、これらの関数は非常に多く、muchより一般的です--any反復可能、オープンであることに注意してくださいファイルまたはその他、プログレッシブアイテム番号に基づいてアイテムのリスト(またはジェネレーター)を返します。したがって、より適切な一般名を使用することをお勧めします;-)。

27
Alex Martelli

別の解決策を提供するために:

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

私はこれが速くて簡単であることを願っています:)

25
KingMak

7行目が必要な場合

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

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

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

slice通常シーケンスの一部を含むオブジェクト。スライスは、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

この関数のもう1つの利点は、最後まで反復子を読み取らないことです。それで、あなたはもっと複雑なことをすることができます:

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]
9
newtover

ファイルの読み取りは非常に速いです。 100MBのファイルを読むのにかかる時間は0.1秒以下です(私の記事 Pythonによるファイルの読み書き を参照)。それゆえ、あなたはそれを完全に読み、それから単一行で作業するべきです。

ここで最も答えがするのは間違っているのではなく、悪いスタイルです。ファイルを開くときは、必ず 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
9
Martin Thoma

これらのいくつかは素敵ですが、それははるかに簡単に行うことができます。

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 +のデータファイルで動作します。がんばろう!

5
Will

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

それ以外の場合は、ここで既に提案されている多くの解決策のうちの1つに従って、あなたが望む行の前にすべての行を読む必要があります。

3
Roman

これはどう:

>>> with open('a', 'r') as fin: lines = fin.readlines()
>>> for i, line in enumerate(lines):
      if i > 30: break
      if i == 26: dox()
      if i == 30: doy()
2
Hamish Grubijan

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()
2
sedic

私はこのアプローチを好みます。それはより汎用的だからです。すなわち、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
Robert Rossney

インポートしても構わないのであれば、 fileinput がまさに必要なことを行います(これは現在行の行番号を読むことができるということです)。

2
ennuikiller
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
2
Roger Pate

これは価値があるもののために、私の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
AWainb
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
    print f.readlines()[26]
    print f.readlines()[30]

With文を使用してファイルを開き、26行目と30行目を印刷してからファイルを閉じます。シンプル!

1
user3901273

ファイルオブジェクトには.readlines()メソッドがあり、ファイルの内容のリストをリスト項目ごとに1行で表示できます。その後は、通常のリストスライス手法を使用できます。

http://docs.python.org/library/stdtypes.html#file.readlines

1
Josh Wright

誰かがすでに述べたこのシンタックスでこれを非常に簡単に行うことができますが、それを行うのがはるかに簡単な方法です。

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

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
crazy_daffodils

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

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

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

with open(file) as f:
    f.seek(n*l)
    line = f.readline()  # please notice the s at the end!
    last_pos = f.tell()

免責事項これは同じ長さのファイルに対してのみ有効です。

1
Michael Dorner

希望の行を印刷します。必要な行の上/下に行を印刷します。

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)すなわちdline( "file path"、line_number、もしあなたが検索した行の上の行がより低い-1に対して1を与えるならこれはオプションのデフォルト値ですとられる0)

0
sudhir tataraju

かなり早く、要点を述べています。

テキストファイルの特定の行を印刷します。 "lines2print"リストを作成し、列挙がlines2printリストの "in"になったときに印刷するだけです。余分な '\ 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]

または、listが小さい場合は、内包表記のリストとしてlistを入力するだけです。

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