개발/Python

[파이썬] 파일을 읽으면 파일 핸들이 계속 열려 있어야 할까?

MinorMan 2023. 1. 22. 03:10
반응형

<질문>

전체 파일을 읽으면content = open('Path/to/file', 'r').read()스크립트가 종료될 때까지 파일 핸들이 열려 있습니까? 전체 파일을 읽는 더 간결한 방법이 있습니까?


<답변1>

그 질문에 대한 답은 특정 Python 구현에 따라 다소 다릅니다.

이것이 무엇인지 이해하려면 실제 상황에 특히 주의를 기울이십시오.file물체. 코드에서 해당 개체는 식에서 한 번만 언급되며 다음 직후에 액세스할 수 없게 됩니다.read()전화가 돌아옵니다.

이것은 파일 객체가 가비지임을 의미합니다. 남은 유일한 질문은 "가비지 수집기가 언제 파일 개체를 수집합니까?"입니다.

참조 카운터를 사용하는 CPython에서는 이러한 종류의 쓰레기가 즉시 발견되므로 즉시 수집됩니다. 이것은 일반적으로 다른 파이썬 구현에는 해당되지 않습니다.

파일이 닫혀 있는지 확인하는 더 나은 솔루션은 다음 패턴입니다.

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

블록이 끝난 직후에 항상 파일을 닫습니다. 예외가 발생하더라도.

편집: 더 자세히 설명하려면 다음을 수행하십시오.

이것 말고도file.__exit__(), "자동으로" 호출됩니다with컨텍스트 관리자 설정, 유일한 다른 방법file.close()자동으로 호출됩니다(즉, 명시적으로 직접 호출하는 경우 제외).file.__del__(). 이것은 우리에게 언제__del__()전화를 받다?

올바르게 작성된 프로그램은 파이널라이저가 프로그램 종료 이전의 어느 지점에서든 실행될 것이라고 가정할 수 없습니다.

--https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203

특히:

개체는 명시적으로 소멸되지 않습니다. 그러나 도달할 수 없게 되면 가비지 수집될 수 있습니다. 구현은 가비지 수집을 연기하거나 완전히 생략할 수 있습니다. 아직 도달할 수 있는 개체가 수집되지 않는 한 가비지 수집이 구현되는 방법은 구현 품질의 문제입니다. [...] CPython은 현재 대부분의 개체가 도달할 수 없게 되는 즉시 수집하지만 순환 참조를 포함하는 가비지를 수집하는 것이 보장되지 않는 순환적으로 연결된 가비지의 지연 감지(선택 사항)와 함께 참조 계산 방식을 사용합니다.

--https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types

(내 강조)

그러나 제안된 대로 다른 구현에는 다른 동작이 있을 수 있습니다. 예를 들어 파이파이has 6 different garbage collection implementations!


<답변2>

당신이 사용할 수있는pathlib.

Python 3.5 이상의 경우:

from pathlib import Path
contents = Path(file_path).read_text()

이전 버전의 Python 사용pathlib2:

$ pip install pathlib2

그 다음에:

from pathlib2 import Path
contents = Path(file_path).read_text()

이것은 실제read_textimplementation:

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

<답변3>

음, 각 줄을 작업하기 위해 파일을 한 줄씩 읽어야 하는 경우 다음을 사용할 수 있습니다.

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

또는 더 나은 방법:

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

<답변4>

파일 내용을 단일 문자열로 검색하는 대신 다음을 수행하는 것이 편리할 수 있습니다.파일을 구성하는 모든 라인의 목록으로 내용 저장:

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

볼 수 있듯이 연결된 메서드를 추가해야 합니다..strip().split("\n")에게the main answer in this thread.

여기,.strip()전체 파일 문자열의 끝에서 공백과 개행 문자를 제거하고.split("\n")전체 파일 문자열을 매번 분할하여 실제 목록을 생성합니다.개행 문자\N.

또한 이 방법으로 전체 파일 내용을 변수에 저장할 수 있습니다.this previous answer.

반응형