열린 파일에서 read ()를 두 번 호출 할 수없는 이유는 무엇입니까?


100

내가하고있는 연습을 위해, 나는 read()방법을 사용하여 주어진 파일의 내용을 두 번 읽으려고 노력하고있다 . 이상하게도 두 번째로 호출하면 파일 내용을 문자열로 반환하지 않는 것 같습니다.

다음은 코드입니다.

f = f.open()

# get the year
match = re.search(r'Popularity in (\d+)', f.read())

if match:
  print match.group(1)

# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', f.read())

if matches:
  # matches is always None

물론 이것이 가장 효율적이거나 최선의 방법이 아니라는 것을 알고 있습니다. 이것은 여기서 요점이 아닙니다. 요점은, 왜 read()두 번 전화 할 수 없습니까? 파일 핸들을 재설정해야합니까? 아니면 파일을 닫거나 다시여시겠습니까?


2
읽기가 파일의 상태를 변경하지 않는다는 아이디어를 어디서 얻었습니까? 어떤 참조 또는 튜토리얼을 사용하고 있습니까?
S.Lott

파일을 닫고 다시 열면 아래 답변을 기반으로 작동해야한다고 생각합니다.
Anthony

1
@Shynthriir : 파일을 닫고 다시 여는 것은 시스템에 다른 영향을 미칠 수 있으므로 항상 좋은 생각은 아닙니다 (임시 파일, incron 등).
Ignacio Vazquez-Abrams

3
난 그냥 명백한 진술 할 : 당신은 DID 회) (통화 읽기!

4
W / R / T / S.Lott, 그리고 5 년 후 : 이것은 정말로 파이썬 문서에 있어야합니다. 하나 ... 하나는 불변 데이터 / 기능적인 스타일의 프로그래밍 작업에 사용되는 특히, 파일 객체를 읽는 것은 아무것도의 상태를 변경하는 것이라고 가정해야한다고 명확하지 않다
폴 Gowder

답변:


157

호출 read()하면 전체 파일을 읽고 파일 끝에 읽기 커서가 남습니다 (더 이상 읽을 내용 없음). 한 번에 라인의 특정 숫자를 읽을 찾고 있다면 당신은 사용할 수 있습니다 readline(), readlines()또는 반복 처리로 라인을 통해 for line in handle:.

질문에 직접 답하려면 파일을 읽은 후 읽기 커서를 파일의 시작 부분으로 되 돌리는 데 read()사용할 수 있습니다 seek(0)(문서는 여기에 있음 ). 파일이 너무 크지 않을 것임을 알고 있다면 read()findall 표현식에서 사용하여 출력을 변수에 저장할 수도 있습니다 .

추신. 작업이 끝나면 파일을 닫는 것을 잊지 마십시오.)


4
+1, 예, 불필요한 파일 I / O를 피하기 위해 임시 변수를 읽으십시오. (명시 적) 변수가 적기 때문에 메모리를 절약하는 것은 잘못된 경제입니다.
Nick T

2
@NickT : 여러 번 읽는 작은 파일이 OS (적어도 Linux / OSX에서는)에 의해 캐시되므로 두 번 읽기위한 추가 파일 I / O가 없습니다. 메모리에 맞지 않는 대용량 파일은 캐시되지 않지만 스와핑을 시작하기 때문에 변수로 읽어 들이고 싶지 않습니다. 따라서 의심스러운 경우 항상 여러 번 읽으십시오. 파일이 작다는 것을 알고 있다면 가장 좋은 프로그램을 제공하는 모든 작업을 수행하십시오.
Claude

3
분해는 with.
Cees Timmerman

30

네, 위와 같이 ...

나는 단지 예를 쓸 것이다.

>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output

17

지금까지이 질문에 답한 모든 사람은 절대적으로 옳 read()습니다. 파일을 통해 이동하므로 호출 한 후에는 다시 호출 할 수 없습니다.

추가 할 것은 특정 경우에 처음으로 돌아가거나 파일을 다시 열 필요가 없으며 읽은 텍스트를 지역 변수에 저장하고 두 번 사용할 수 있다는 것입니다. 프로그램에서 원하는만큼 여러 번 :

f = f.open()
text = f.read() # read the file into a local variable
# get the year
match = re.search(r'Popularity in (\d+)', text)
if match:
  print match.group(1)
# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', text)
if matches:
  # matches will now not always be None

1
+1 실제로 이것은이 연습을 위해 제안 된 솔루션이었습니다 ( code.google.com/intl/de-DE/edu/languages/google-python-class/… ). 그러나 어떻게 든 문자열을 변수에 저장할 생각은 없었습니다. 오!
helpermethod

1
Python3에서는 pathlib를 사용합니다. from pathlib import Path; text = Path(filename).read_text()열기, 닫기 등을 처리합니다.
PaulMcG

14

읽기 포인터는 마지막으로 읽은 바이트 / 문자 뒤로 이동합니다. seek()메서드를 사용하여 읽기 포인터를 처음으로 되감습니다.


2

열려있는 모든 파일에는 연관된 위치가 있습니다.
read ()하면 그 위치에서 읽습니다. 예를 들어 read(10)새로 열린 파일에서 처음 10 바이트를 read(10)읽은 다음 다른 파일 은 다음 10 바이트를 읽습니다. read()인수 없이는 파일의 모든 내용을 읽고 파일의 끝에 파일 위치를 남깁니다. 다음에 전화 할 때는 read()읽을 것이 없습니다.

seek파일 위치를 이동하는 데 사용할 수 있습니다 . 또는 귀하의 경우에는 하나를 수행 read()하고 두 검색에 대한 결과를 유지하는 것이 더 좋습니다 .


1

read() 소비합니다 . 따라서 파일을 재설정 하거나 다시 읽기 전에 시작을 찾을 수 있습니다. 또는 작업 read(n)에 적합한 경우을 사용 하여 n바이트 만 사용할 수 있습니다 .


1

읽기 방법은 항상 어두운 골목길을 걷는 것과 같습니다. 당신은 조금 내려 가서 멈췄지만 걸음 수를 세지 않으면 당신이 얼마나 멀리 있는지 알 수 없습니다. Seek는 위치를 변경하여 솔루션을 제공하고 다른 옵션은 파일을 따라 위치를 반환하는 Tell입니다. 파이썬 파일 api가 읽기를 결합하고 read_from (position, bytes)를 탐색하여 더 간단하게 만들 수 있습니다. 그럴 때 까지이 페이지를 읽어야 합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.