명시 적으로 파일을 닫는 것이 중요합니까?


149

파이썬에서을 호출하지 않고 파일을 열거 close()나 파일을 닫지 만 try- finally또는 " with"문을 사용하지 않으면 이것이 문제입니까? 아니면 파이썬 가비지 수집에 의존하여 모든 파일을 닫는 코딩 연습으로 충분합니까? 예를 들어, 이렇게하는 경우 :

for line in open("filename"):
    # ... do stuff ...

... 파일을 닫을 수 없으며 예외로 파일을 닫을 수 없기 때문에 이것이 문제입니까? 또는 for파일이 범위를 벗어 났기 때문에 진술 의 결론에서 분명히 닫히 겠습니까?


13
블록 끝에서 파일이 범위를 벗어나지 않습니다for . 참조 횟수는 0이되어 자동으로 닫히지 만 함수, 클래스 및 모듈 만 다른 복합 명령문이 아닌 Python에서 범위를 정의합니다.
agf

18
문제가 아닌 한 문제가되지 않습니다. OS 수준에서 스크립트가 종료되면 스크립트가 연 모든 파일이 닫히므로 버리기 도구 스크립트에서 파일을 닫는 것에 대해 걱정할 필요가 없습니다. 그러나 프로세스는 유지 관리 할 수있는 열린 파일 수에 제한이 있으므로 오래 지속되거나 복잡한 스크립트는 더주의해야합니다. 어쨌든 파일을 닫는 것이 좋습니다.
Russell Borogove

3
@agf : 파일의 범위를 벗어난 것은 아니지만 for블록과 함수 / 클래스 / 모듈 의 구분과는 관련이 없습니다 . 객체보다 범위가없고 이름 만있는 것보다 훨씬 간단합니다. 이 개체를 나타내는 이름이 없으므로 범위를 유지하거나 범위를 벗어나는 것은 없습니다.
최대

@max 내 의견은 for루프 와 관련된 범위가 있다는 가정을 수정 하고 파일이 완전히 다른 이유로 닫혔다는 언급입니다. 그것은으로하지 않는 범위가 무엇인지 가 여기에 해당 아니다으로, 파이썬.
agf

@max for 루프에 대한 암시 적 참조가 있습니다. 이것은 의미론의 논쟁입니다
Peter R

답변:


126

귀하의 예에서 파일은 인터프리터가 종료되기 전에 닫히지 않을 수 있습니다. CPython의 현재 버전에서 CPython은 참조 카운트를 기본 가비지 콜렉션 메커니즘으로 사용하지만 언어의 기능이 아닌 구현 세부 사항이므로 for 루프의 끝에 파일이 닫힙니다. 파이썬의 다른 구현은 이런 식으로 작동한다고 보장되지 않습니다. 예를 들어 IronPython, PyPy 및 Jython은 참조 횟수를 사용하지 않으므로 루프가 끝날 때 파일을 닫지 않습니다.

CPython의 가비지 콜렉션 구현을 사용하는 것은 코드의 이식성을 떨어 뜨리기 때문에 나쁜 습관입니다. CPython을 사용하는 경우 리소스 누수가 없을 수 있지만 참조 계산을 사용하지 않는 Python 구현으로 전환 한 경우 모든 코드를 살펴보고 모든 파일이 올바르게 닫혀 있는지 확인해야합니다.

귀하의 예를 들어 :

with open("filename") as f:
     for line in f:
        # ... do stuff ...

8
사용 with open() as f후 파일 을 자동으로 닫습니까?
Rohan

24
예 @Rohan, 작은 마법이라는 것을 with문을 제공하지만, 과정의 목적을 작동이 마법은 특별한 방법을 가지고 있어야 위해 __enter__그리고 __exit__객체가 않습니다 후자에, close그리고 다른 정리 물건 필요가에서 할 것을 with성명서 끝 ...
Copperfield

1
참고 :이 답변은 "닫을 때"만 설명하고 "열린 상태로 유지"하는 경우에는 설명하지 않습니다. 후자의 경우 "파일이 열려 있으면 어떻게됩니까?"를 읽으십시오. 이 답변의 일부 ( askubuntu.com/questions/701491/… )
RayLuo

또한 파일 내용을 비우지 않았으므로 파일을 닫지 않으면 파일이 잘릴 수 있습니다.
Erwan Legrand

따라서 파일을 닫지 않으면 프로그램 실행이 중지되면 메모리가 다시 확보됩니까? 아니면 실제로 통역사 전체를 그만 두어야합니까?
Pro Q

22

일부 파이썬은 더 이상 참조되지 않을 때 파일을 자동으로 닫는 반면, 다른 파이썬은 그렇지 않고 파이썬 인터프리터가 종료 될 때 파일을 닫는 것은 O / S에 달려 있습니다.

파일을 닫는 Python의 경우에도 타이밍이 보장되지 않습니다. 즉시 또는 몇 초 / 분 / 시간 / 일이 될 수 있습니다.

따라서 사용중인 Python에서 문제가 발생하지는 않지만 파일을 열어 두는 것은 좋은 습관이 아닙니다. 실제로 cpython 3에서는 파일을 닫지 않았다면 시스템에서 파일을 닫아야한다는 경고가 표시됩니다.

도덕 : 스스로를 정리하십시오. :)


9
CPython에서 더 이상 참조되지 않으면 파일이 닫히지 만 언어 기능은 아닙니다. 그렇다면 당신은 그것에 행복하게 의존 할 수 있습니다.
피터 그레이엄

9

이 특별한 경우에 그러한 구조를 사용하는 것이 안전하지만 그러한 관행을 일반화하기위한 몇 가지주의 사항이 있습니다.

  • 실행은 파일 디스크립터가 부족할 수 있습니다.
  • 일부 시스템 (예 : win32)에서 해당 파일을 삭제하지 못할 수 있습니다
  • CPython 이외의 것을 실행하면 파일이 언제 닫히는 지 알 수 없습니다.
  • 파일을 쓰기 또는 읽기 / 쓰기 모드로 열면 데이터가 플러시되는 시점을 알 수 없습니다

3

파일은 가비지 수집되어 닫힙니다. GC는 귀하가 아닌 폐쇄 시점을 결정합니다. 파일 사용을 마치는 즉시 파일을 닫지 않으면 열린 파일 핸들 제한에 도달 할 수 있으므로이 방법은 권장되지 않습니다. for당신의 루프 내에서 더 많은 파일을 열어두고 남아 있다면 어떨까요?


그러나 for 루프 내에서 다른 파일을 연 경우 명시 적으로 닫을 지 여부에 관계없이 동시에 두 개 이상의 파일이 열릴 수 있습니다. 파일이 범위를 벗어나 자마자 파일이 반드시 가비지 수집 될 필요는 없으므로 명시 적으로 수행하면 더 빨리 닫히는 것입니까? 예외가 발생하는 경우는 어떻습니까 (최종 사용 / 시도 vs 사용하지 않을 경우)?
user553702

1
CPython에서 참조 횟수는 for명령문 이후에 참조 횟수를 수집 하므로 다음 가비지 콜렉션 실행을 기다릴 필요가 없습니다.
agf

3

안녕 동일한 파이썬 스크립트에서 내용을 사용하려고 할 때 파일 설명자를 닫는 것이 매우 중요합니다. 나는 오늘 너무 오래 헥타르 디버깅 후 깨달았습니다. 파일 디스크립터를 닫은 후에 만 ​​내용이 편집 / 제거 / 저장되며 변경 사항이 파일에 영향을주기 때문입니다!

따라서 새 파일에 내용을 쓴 다음 fd를 닫지 않고 내용을 읽는 다른 셸 명령에서 해당 파일 (fd 아님)을 사용하고 있다고 가정합니다. 이 상황에서 예상대로 쉘 명령의 내용을 얻지 못하고 디버그하려고하면 쉽게 버그를 찾을 수 없습니다. 내 블로그 항목 http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html 에서 더 많은 내용을 읽을 수도 있습니다 .


1

I / O 프로세스 중에 데이터가 버퍼링됩니다. 즉, 파일에 기록되기 전에 임시 위치에 유지됩니다.

파이썬은 버퍼를 플러시하지 않습니다. 즉, 데이터가 파일에 쓰여질 때까지 쓰기가 끝날 때까지 기다립니다. 이를 수행하는 한 가지 방법은 파일을 닫는 것입니다.

닫지 않고 파일에 쓰면 데이터가 대상 파일로 만들지 않습니다.

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