특정 줄만 읽기


답변:


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

참고 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

3
이것으로 내 작은 쇠고기는 A) 당신이 오픈 / 클로즈 페어 대신에 사용하고 몸을 짧게 유지하고 싶다는 것입니다. B) 그러나 몸은 그렇게 짧지 않습니다. 속도 / 공간과 Pythonic 사이의 절충과 같습니다. 최고의 솔루션이 무엇인지 잘 모르겠습니다.
Hamish Grubijan

5
과대 평가 된 결과, 파이썬은 13 년 이상 없이도 잘 지 냈습니다
Dan D.

38
@ Dan D. 전기는 과대 평가되었고, 인류는 그것없이 2 만년 이상 잘 지 냈습니다. ;-) 'with'는 더 안전하고 읽기 쉽고 줄을 짧게 만듭니다.
Romain Vincent

9
왜 for 루프를 사용하는지의 의미를 이해하지 못한다고 생각합니다 big file. 루프가 색인에 도달하는 데 몇 년이 걸릴 것입니다
devssh

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 질문) 있습니다.

위에 링크 된 파이썬 문서 인용하기 :

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

변경 4원하는 줄 번호로 됩니다. 카운트가 0부터 시작하므로 4는 다섯 번째 줄을 가져옵니다.

파일이 매우 커서 메모리를 읽을 때 문제가 발생하면 @Alok의 조언 을 받아 enumerate ()를 사용 하는 것이 좋습니다 .

결론적으로:

  • 작은 파일을위한 빠른 솔루션으로 fileobject.readlines()또는 사용하십시오 for line in fileobject.
  • linecache더 많은 파일을 읽는 데 매우 빠른 더 우아한 솔루션을 사용 하면 반복적으로 가능합니다.
  • @Alok의 조언을enumerate() 받아 용량이 크거나 메모리에 맞지 않는 파일에 사용 하십시오. 파일을 순차적으로 읽으므로이 방법을 사용하면 속도가 느려질 수 있습니다.

7
좋은. 방금 linecache모듈 의 소스를 보았고 메모리에서 전체 파일을 읽는 것처럼 보입니다. 따라서 임의 액세스가 크기 최적화보다 중요한 경우 linecache가장 좋은 방법입니다.
Alok Singhal

7
linecache.getlin ( 'some_file', 4)으로 5 번째 줄이 아닌 4 번째 줄을 얻습니다.
Juan

재미있는 사실 : 두 번째 예제에서 목록 대신 세트를 사용하면 O (1) 실행 시간이 표시됩니다. 목록에서 조회는 O (n)입니다. 내부 집합은 해시로 표시되므로 O (1) 실행 시간이 발생합니다. 이 예제에서는 큰 문제가 아니지만 많은 수의 목록을 사용하고 효율성을 염두에두면 세트가 좋습니다.
rady

linecache파이썬 소스 파일에서만 작동하는 것으로 보입니다
Paul H

linecache.getlines('/etc/passwd')[0:4]첫 번째, 두 번째, 세 번째 및 네 번째 줄을 읽는 데 사용할 수도 있습니다 .
zyy

30

빠르고 컴팩트 한 접근 방식은 다음과 같습니다.

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

이것은 열려있는 파일과 같은 객체 thefile(디스크 파일에서 또는 소켓이나 다른 파일과 같은 스트림을 통해 열어야하는지 여부를 호출자에게 맡김)와 0부터 시작하는 라인 인덱스 집합을 받아들이고 whatlines, 메모리 풋 프린트가 낮고 속도가 적당합니다. 리턴되는 라인 수가 많으면 생성기를 선호 할 수 있습니다.

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

이것은 기본적으로 루핑에만 적합합니다-유일한 차이점은 return명령문 에서 사각형 괄호 대신 둥근 괄호를 사용하여 목록 이해와 생성기 표현식을 만드는 것입니다.

또한 노트 '선'과의 언급에도 불구하고 "파일"이 기능은 많은 것을, 훨씬 더 일반적으로는 - 그들은 작동합니다 모든 항목의 목록 (또는 발전기를) 반환, 그것을 열린 파일 또는 어떤 다른 일, 반복 가능한 점진적인 항목 번호를 기준으로합니다. 따라서 더 적절한 일반 이름을 사용하는 것이 좋습니다 .-).


@ephemient, 나는 동의하지 않습니다 .genexp는 부드럽고 완벽하게 읽습니다.
Alex Martelli

훌륭하고 우아한 솔루션, 감사합니다! 실제로 생성기 표현식으로 큰 파일도 지원해야합니다. 이보다 더 우아해질 수는 없습니까? :)
Samuel Lampa

좋은 해결책, 이것은 @AdamMatan이 제안한 것과 어떻게 비교됩니까? Adam 솔루션은 추가 정보 (단수 적으로 증가하는 줄 번호)를 활용하여 더 빨리 중지 할 수 있으므로 더 빠를 수 있습니다. 메모리에로드 할 수없는 10GB 파일이 있습니다.
Mannaggia

2
그것은이 답변에 충분히 강조하지,하지만 @Mannaggia whatlines해야 set하기 때문에, if i in whatlines세트보다는 (분류) 목록을 빠르게 실행됩니다. 나는 그것을 먼저 알아 차리지 못하고 대신 정렬 된 목록을 가진 내 자신의 추악한 솔루션을 고안했습니다 (매번 목록을 스캔 할 필요는 없지만 그렇게하지는 않습니다 if i in whatlines). 성능의 차이는 무시할 수 있습니다 (데이터와 함께). 해결책은 훨씬 더 우아합니다.
Victor K

28

다른 솔루션을 제공하기 위해 :

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

나는 이것이 쉽고 빠르기를 바랍니다 :)


1
이것이 가장 최적의 솔루션이기를 바랍니다.
maniac_user

2
전체 파일을 메모리로 읽습니다. file.read (). split ( '\ n')을 호출 한 다음 배열 인덱스 조회를 사용하여 관심있는 라인을 얻을 수 있습니다.
duhaime

@duhaime
anon

14

7 행을 원한다면

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

14
산뜻한. 그러나이 방법으로 close()파일을 열 때 파일 은 어떻게 됩니까?
Milo Wielondek

1
@ 0sh 우리는 닫아야합니까?
Ooker

1
예. "with"를 사용하여 파일을 열면 자체적으로 닫힙니다.
reetesh11

10

완전성을 위해 여기에 또 하나의 옵션이 있습니다.

파이썬 문서 의 정의부터 시작해 봅시다 .

슬라이스 일반적으로 시퀀스의 일부를 포함하는 객체입니다. 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으로 파일 읽기 및 쓰기 참조) ). 따라서 당신은 그것을 완전히 읽고 한 줄로 작업해야합니다.

대부분의 대답은 잘못된 것이 아니라 나쁜 스타일입니다. 파일 열기는 항상 다음을 수행해야합니다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

거대한 파일

파일이 많고 메모리 소비가 중요한 경우 파일을 한 줄씩 처리 할 수 ​​있습니다.

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

IMO 그것은 처음 30 줄을 얻는 것만으로 알 수없는 길이의 전체 파일을 읽는 것이 정말 나쁜 스타일입니다. 메모리 소비는 무엇입니까.
return42

@ return42 그것은 응용 프로그램에 매우 의존합니다. 많은 경우 텍스트 파일이 사용 가능한 메모리보다 크기가 작다고 가정하는 것이 좋습니다. 잠재적으로 큰 파일이 있으면 내 답변을 편집했습니다.
마틴 토마

귀하의 추가에 감사드립니다 . alok answer 과 동일 합니다. 그리고 미안합니다. 응용 프로그램에 달려 있다고 생각하지 않습니다. IMO는 항상 더 많은 줄을 읽지 않는 것이 좋습니다.
return42

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 바이트 수?) 실제로 속도 향상을 원한다면 문자 수를 직접 계산할 수 있습니다 (줄 바꿈과 같은 보이지 않는 문자를 포함해야 함).

그렇지 않으면 여기에 이미 제안 된 많은 솔루션 중 하나에 따라 원하는 줄보다 먼저 모든 줄을 읽어야합니다.


3

큰 텍스트 파일 file이 엄격하게 구조화되어 있으면 (모든 줄의 길이가 동일 함 l)-세 n번째 줄에 사용할 수 있습니다

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

고지 사항 같은 길이의 파일에만 작동합니다!


2

이건 어때요:

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

사실, 이것은 Alok의 것보다 덜 효율적이지만, with 문을 사용합니다.)
Hamish Grubijan

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

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()반복자에 대한 첫 번째 호출 이 소진되고 두 번째 호출이 빈 목록을 반환하거나 오류를 던질 것입니다 (어떤 것을 기억할 수 없음)
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

원저자 : Frank Hofmann


1

상당히 빠르고 요점.

텍스트 파일에 특정 줄을 인쇄합니다. "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]

또는 목록이 작은 경우 이해력에 목록으로 목록을 입력하십시오.

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

실행 ----> dline ( "D : \ dummy.txt", 6) 즉 dline ( "파일 경로", 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
이것은 얻을 수있는만큼 해적이지 않습니다.
SilentGhost

readline과 readline을 사용할 수 없으므로 잘못된 결과를 제공합니다 (각각 현재 읽기 위치를 변경 함).

첫 번째 코드에서 거대한 오류가 간과되어 죄송합니다. 오류가 수정되었으며 현재 코드가 예상대로 작동합니다. 내 잘못을 지적 해 주셔서 감사합니다. Roger Pate
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.