한 줄의 코드로 파일 읽기 및 닫기


128

이제는 다음을 사용합니다.

pageHeadSectionFile = open('pagehead.section.htm','r')
output = pageHeadSectionFile.read()
pageHeadSectionFile.close()

그러나 코드를 더 좋아 보이게하려면 다음을 수행하십시오.

output = open('pagehead.section.htm','r').read()

위의 구문을 사용할 때 시스템 리소스를 확보하기 위해 파일을 닫으려면 어떻게해야합니까?


19
하나의 라이너에 대해 본질적으로 더 매력적인 것은 없습니다. 코드는 작성된 것보다 훨씬 자주 읽 히며 "차가움"이 아닌 이해를 위해 작성해야합니다. 유일한 예외는 언어로 잘 알려진 관용구가 있지만이 경우에는 하나도 모르는 것입니다.
drdwilcox

17
@ drdwilcox : Cryptic one-liners는 나쁘고 선언적인 one-liner는 좋습니다. 코어에 단일 함수 호출로 파일을 읽을 수있는 함수 래퍼가없는 이유는 없습니다 (적어도 하나는 볼 수 없습니다). 같은 것 contents = os.readfile(path). 더 멋진 것을하고 싶다면 좋아합니다 with open(path) as fd: contents = fd.read(). 물론 하나는 자체 래퍼를 작성할 수 있지만 핵심은 프로그래머에게 추상화에 유용한 기능을 제공하는 것입니다.
tokland

5
코드가 작성된 것보다 훨씬 더 많이 읽힌다는 것은 사실이지만 짧은 코드만큼 긴 코드가 좋은 것은 더 이상 잘못 될 수 없습니다. 이해하기 어려운 영리한 속임수를 사용하지 않고 코드를 최대한 짧게 만드는 데 시간을 투자하면 코드를 읽을 때 투자액이 계속해서 지불됩니다. 작성하는 모든 줄은 코드를 읽는 모든 사람에게 장애가되므로 가능한 한 적게 쓰려고 노력해야합니다. 파스칼 (Pascal)의 유명한 인용문을 기억하십시오.
John Williams

답변:


195

실제로 닫을 필요는 없습니다. 파이썬은 가비지 수집 중이나 프로그램 종료시 자동으로 처리합니다. 그러나 @delnan이 지적했듯이 여러 가지 이유로 명시 적으로 닫는 것이 좋습니다.

따라서 짧고 간단하며 명시 적으로 유지하기 위해 할 수있는 일 :

with open('pagehead.section.htm','r') as f:
    output = f.read()

이제는 두 줄에 불과하고 읽기 쉽습니다.


2
@ 1qazxsw2 with 을 사용하면 파일 리소스가 제대로 닫힙니다.
David Alber

13
첫 번째 문장 다시 : 파이썬은 결국 그것을 닫을 것 입니다. 그렇다고해서 닫는 것을 잊어야한다는 의미는 아닙니다. 재 계산을해도 파일이 생각하고 원하는 것보다 훨씬 오래 열려있을 수 있습니다 (예 : 주기로 참조되는 경우). 이것은 적절한 GC를 가진 파이썬 구현에서 세 번갑니다. 여기서 어떤 특정 시점에 GC가 있다고 보장 할 수는 없습니다. CPython 문서 조차도 이와 같은 정리를 위해 GC에 의존해서는 안된다고 말합니다. 답의 후자는 굵게 표시해야합니다.

6
실제로 하나의 라이너 가 필요한 경우 output = f.read()부품 다음에 동일한 줄에 부품 을 넣을 수 있습니다 :.
Karl Knechtel

1
"한 줄의 코드로 파일 열기 및 닫기"이것은 두 줄이며 질문에 대한 답은 아닙니다.
user5359531

1
구현에 따라 다릅니다. Sven의 답변을 참조하십시오.
Tim Pietzcker 2016 년

71

Python Standard Library Pathlib 모듈은 원하는 것을 수행합니다.

Path('pagehead.section.htm').read_text()

Path를 가져 오는 것을 잊지 마십시오 :

jsk@dev1:~$ python3
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pathlib import Path
>>> (Path("/etc") / "hostname").read_text()
'dev1.example\n'

Python 27에서 백 포트 설치 pathlib또는pathlib2


8
제안하는 다른 답변 with은 훌륭하지만 with표현이 아닌 진술입니다. 이 pathlib답변은 Python 식에 포함될 수있는 원래 질문에 대한 유일한 답변입니다. 같은 것SECRET_KEY = os.environ.get('SECRET_KEY') or pathlib.Path('SECRET_KEY').read_bytes()
LeoRochael

24

CPython을 사용하면 파일 오브젝트가 즉시 가비지 수집되므로 행이 실행 된 직후 파일이 닫힙니다. 그러나 두 가지 단점이 있습니다.

  1. CPython과 다른 Python 구현에서 파일은 종종 즉시 닫히지 않고 나중에 제어 할 수없는 범위에서 닫힙니다.

  2. Python 3.2 이상에서 ResourceWarning활성화하면을 발생시킵니다.

하나의 추가 라인을 투자하는 것이 좋습니다.

with open('pagehead.section.htm','r') as f:
    output = f.read()

이렇게하면 모든 상황에서 파일이 올바르게 닫힙니다.


17

이를 위해 특별한 라이브러리를 가져올 필요가 없습니다.

일반 구문을 사용하면 파일을 읽고 닫을 수 있습니다.

with open("/etc/hostname","r") as f: print f.read() 

또는

with open("/etc/hosts","r") as f: x = f.read().splitlines()

이것은 행을 포함하는 배열 x를 제공하며 다음과 같이 인쇄 할 수 있습니다.

for line in x: print line

이 단일 라이너는 유지 관리에 매우 유용합니다. 기본적으로 자체 문서화입니다.


8

당신이 할 수있는 일은 with문장 을 사용하고 한 줄에 두 단계를 쓰는 것입니다.

>>> with open('pagehead.section.htm', 'r') as fin: output = fin.read();
>>> print(output)
some content

with문장은 __exit__코드에 문제가 발생하더라도 주어진 객체의 함수 를 호출하도록주의를 기울입니다 . try... finally구문에 가깝습니다 . 에 의해 반환 된 개체를 들어 open, __exit__파일 폐쇄에 해당합니다.

이 문장은 Python 2.6에서 도입되었습니다.


작은 설명 : 문서 에 따르면 withPython 2.5에서 소개되었지만 에서 명시 적으로 가져와야 했습니다 __future__. 파이썬 2.6의 모든 컨텍스트에서 사용할 수있게되었습니다.
David Alber

5

ilio 사용 : (inline io) :

open (), read (), close () 대신 하나의 함수 호출.

from ilio import read

content = read('filename')

2
with open('pagehead.section.htm')as f:contents=f.read()

4
이 답변이 톱 3 답변과 어떻게 다른가요?
모든 근로자가 필수적

4
가장 큰 차이점은 질문과 같이 한 줄에 불과하다는 것입니다. 개인적으로 나는 그 이상을 찾을 수 없지만 실제로 자신의 질문에 기여하기보다는 내 일을 비평 할 수 있습니다.

3
파이썬에서 파일 열기, 읽기 및 닫기를 달성하는 가장 짧은 기본 제공 방법은 파일이 1 줄로 축소되는지 여부에 관계없이 2 개의 논리 줄을 사용하는 것입니다. 따라서이 답변이 3 개의 원래 답변과 효과적으로 다른 것으로 보이지 않습니다.
모든 근로자가 필수적

1
'효과적으로'다른지 여부는 중요하지 않습니다. 이 페이지 python -c에 명령 줄에서 사용할 수있는 한 줄 구문을 찾았 으므로 2 줄 답변을 게시해도 도움이되지 않습니다.
user5359531

1
@ user5359531 난 당신의 지점이 표시되지 않는 : 당신은 당신이 파이썬 표현식을 인용 수 있다는 것을 알고 ", 사용 ;후 2 개 지침을 추가하고, 삭제 줄 바꿈 :? 다음 표현은 저에게 잘 작동합니다.$> python -c "with open('some file', 'r') as f: print(next(f))"
Joël

2

이것을 달성하는 가장 자연스러운 방법은 함수를 정의하는 것이라고 생각합니다.

def read(filename):
    f = open(filename, 'r')
    output = f.read()
    f.close()
    return output

그런 다음 다음을 수행 할 수 있습니다.

output = read('pagehead.section.htm')

0

로그 파일에 정리 한 것을 둘러싼 몇 줄을 가져와야 할 때 종종 다음과 같은 작업을 수행합니다.

$ grep -n "xlrd" requirements.txt | awk -F ":" '{print $1}'
54

$ python -c "with open('requirements.txt') as file: print ''.join(file.readlines()[52:55])"
wsgiref==0.1.2
xlrd==0.9.2
xlwt==0.7.5

1
완전히 원래의 주제와 관련이없는,하지만 당신은에 보일 것입니다 grep -A <n>, grep -B <n>그리고 grep -C <n>그것이 도움이 될 것입니다 경우. 추가 정보 : stackoverflow.com/a/9083/1830159
Liam Stanley

0

를 사용하면 한 줄에 more_itertools.with_iter해당하는 것을 열고, 읽고, 닫고 할당 할 수 output있습니다 (import 문 제외).

import more_itertools as mit


output = "".join(line for line in mit.with_iter(open("pagehead.section.htm", "r")))

가능하지만 파일의 내용을 변수에 할당하는 것 이외의 다른 접근 방법, 즉 지연 반복을 찾고 싶습니다. 이는 전통적인 with블록을 사용하거나 위의 예에서 제거 join()하고 반복 하여 수행 할 수 있습니다 output.


oneliner 내부로도 가져올 수 있습니다. "".join(line for line in __import__('more_itertools').with_iter(open("pagehead.section.htm", "r")))이것은 잘 작동하며 가져 오기에 대한 라인이 필요하지 않습니다.
melwil

1
나는 당신에게 완전히 동의합니다. 그러나 oneliners로 해결 작업을 논의하는 동안 나는 동의 한 결과가 새로운 파이썬 쉘에 붙여진 단일 코드 행이어야한다는 주장에서 종종 나 자신을 발견했습니다. 이러한 과제는 pep8과 거의 일치하지 않습니다. 코드를 작성하는 좋은 방법은 아니며 가져 오기가 필요하지 않은 팁일뿐입니다.
melwil

0

그 따뜻하고 퍼지 느낌을 원한다면 함께 가십시오 .

python 3.6의 경우, IDLE을 새로 시작하여이 두 프로그램을 실행하여 런타임을 제공했습니다.

0.002000093460083008  Test A
0.0020003318786621094 Test B: with guaranteed close

큰 차이는 없습니다.

#--------*---------*---------*---------*---------*---------*---------*---------*
# Desc: Test A for reading a text file line-by-line into a list
#--------*---------*---------*---------*---------*---------*---------*---------*

import sys
import time

#                                  # MAINLINE
if __name__ == '__main__':
    print("OK, starting program...")

    inTextFile = '/Users/Mike/Desktop/garbage.txt'

#                                  # Test: A: no 'with;
    c=[]
    start_time = time.time()
    c = open(inTextFile).read().splitlines()
    print("--- %s seconds ---" % (time.time() - start_time))

    print("OK, program execution has ended.")
    sys.exit()                     # END MAINLINE

산출:

OK, starting program...
--- 0.002000093460083008 seconds ---
OK, program execution has ended.

#--------*---------*---------*---------*---------*---------*---------*---------*
# Desc: Test B for reading a text file line-by-line into a list
#--------*---------*---------*---------*---------*---------*---------*---------*

import sys
import time

#                                  # MAINLINE
if __name__ == '__main__':
    print("OK, starting program...")

    inTextFile = '/Users/Mike/Desktop/garbage.txt'

#                                  # Test: B: using 'with'
    c=[]
    start_time = time.time()
    with open(inTextFile) as D: c = D.read().splitlines()
    print("--- %s seconds ---" % (time.time() - start_time))

    print("OK, program execution has ended.")
    sys.exit()                     # END MAINLINE

산출:

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