Python에서 "with open"을 사용하여 여러 파일을 열려면 어떻게해야합니까?


672

나는 한 번에 파일의 몇 가지를 변경하려면 IFF에 내가 그들 모두에 쓸 수 있습니다. 어떻게 든 여러 개의 열린 호출을 with진술 과 결합 할 수 있는지 궁금합니다 .

try:
  with open('a', 'w') as a and open('b', 'w') as b:
    do_something()
except IOError as e:
  print 'Operation failed: %s' % e.strerror

이것이 가능하지 않다면이 문제에 대한 우아한 해결책은 무엇입니까?

답변:


1051

파이썬 2.7 (또는 각각 3.1)부터 쓸 수 있습니다

with open('a', 'w') as a, open('b', 'w') as b:
    do_something()

이전 버전의 Python에서는 때때로 contextlib.nested()컨텍스트 관리자를 중첩 하는 데 사용할 수 있습니다 . 다중 파일을 열 때 예상대로 작동하지 않습니다. 자세한 내용은 링크 된 설명서를 참조하십시오.


드문 경우이지만 동시에 가변 개수의 파일을 열려면 contextlib.ExitStackPython 버전 3.3부터 사용할 수 있습니다 .

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Do something with "files"

대부분의 경우 변수 파일 세트가있는 경우 파일을 하나씩 차례로 열고 싶을 것입니다.


5
불행히도, contextlib.nested 문서에 따르면, 파일을 열 때 사용해서는 안됩니다. "네스트 ()를 사용하여 두 파일을 열면 프로그래밍 오류가 발생합니다. 두 번째 파일입니다. "
weronika

41
with변수 파일 목록을 여는 방법이 있습니까?
monkut

23
@monkut : 아주 좋은 질문입니다 (실제로이 질문을 별도의 질문으로 할 수 있습니다). 짧은 대답 : 예 ExitStack. Python 3.3부터 있습니다. 이전 버전의 Python에서는이를 수행하는 쉬운 방법이 없습니다.
Sven Marnach

12
이 구문을 여러 줄에 걸쳐 사용할 수 있습니까?
tommy.carstensen

9
@ tommy.carstensen : 일반적인 줄 연속 메커니즘을 사용할 수 있습니다 . PEP 9에서 권장하는 대로 백 슬래시 줄 연속을 사용하여 쉼표에서 끊어야합니다 .
Sven Marnach

99

그냥 교체 and,하면됩니다 :

try:
    with open('a', 'w') as a, open('b', 'w') as b:
        do_something()
except IOError as e:
    print 'Operation failed: %s' % e.strerror

3
이 구문을 지원하는 Python 버전을 지정해야합니다.
Craig McQueen

58

한 번에 많은 파일을 열거 나 긴 파일 경로를 위해 여러 줄로 나누는 것이 유용 할 수 있습니다. 로부터 파이썬 스타일 가이드 다른 답변에 의견 @Sven Marnach에 의해 제안 :

with open('/path/to/InFile.ext', 'r') as file_1, \
     open('/path/to/OutFile.ext', 'w') as file_2:
    file_2.write(file_1.read())

1
이 들여 쓰기를 통해 다음과 같은 결과를 얻습니다. "flake8 : 연속 들여 쓰기를위한 들여 쓰기 들여 쓰기"
Louis M

@LouisM 기본 파이썬이 아닌 에디터 나 환경에서 나오는 것 같습니다. 그래도 계속 문제가 발생하면 이에 관한 새로운 질문을 작성하고 편집자와 환경에 대해 더 자세한 정보를 제공하는 것이 좋습니다.
Michael Ohlrogge

3
예, 확실히 내 편집자이며 경고 일뿐입니다. 내가 강조하고 싶은 것은 들여 쓰기가 PEP8을 준수하지 않는다는 것입니다. 두 번째 open ()을 첫 번째와 정렬하는 대신 8 개의 공백으로 들여 쓰기해야합니다.
Louis M

2
@LouisM PEP8은 규칙 이 아니라 가이드 라인 이며,이 경우 가장 확실하게 무시할 것입니다.
Nick

2
네, 문제 없어요. 자동 린터를 가진 다른 사람들에게 유용 할 것입니다 :)
Louis M

15

내포 된 진술은 똑같은 일을 할 것이며 내 의견으로는 다루기가 더 간단합니다.

inFile.txt가 있고 두 개의 outFile에 동시에 쓰고 싶다고 가정 해 봅시다.

with open("inFile.txt", 'r') as fr:
    with open("outFile1.txt", 'w') as fw1:
        with open("outFile2.txt", 'w') as fw2:
            for line in fr.readlines():
                fw1.writelines(line)
                fw2.writelines(line)

편집하다:

공감의 이유를 이해하지 못합니다. 답변을 게시하기 전에 코드를 테스트했으며 원하는대로 작동합니다. 질문과 같이 모든 outFile에 씁니다. 중복 쓰거나 쓰지 않습니다. 그래서 나는 왜 내 대답이 잘못된 지, 차선책인지 아닌지 생각합니다.


1
다른 사람이 당신을 어떻게 다운 시켰는지 모르지만, 이것은 내가 필요한 것만 발생하는 세 개의 파일 (하나의 입력, 두 개의 출력)을 가진 유일한 예이기 때문에 나는 당신을 찬성했습니다.
Adam Michael Wood

2
어쩌면 파이썬> 2.6에서 bcoz가 하향 조정되었습니다. 더 많은 파이썬 코드를 작성할 수 있습니다. 과거
엘 루소

2
poo-poohing python 2.6 : CentOS 6 (2020 년 11 월까지 EOL이 아님)에 대한 친근한 알림은 여전히 ​​기본적으로 py2.6을 사용합니다. 따라서이 답변은 여전히 ​​가장 최고의 IMO입니다.
BJ Black

11

Python 3.3부터는 모듈 의 클래스 ExitStack를 사용하여 임의의 수의 파일contextlib 을 안전하게
열 수 있습니다 .

동적 으로 인식되는 상황 인식 객체를 관리 할 수 ​​있으므로 처리 할 파일 수를 모르는 경우 특히 유용 합니다 .

실제로, 설명서에 언급 된 표준 사용 사례는 동적 파일 수를 관리하는 것입니다.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

세부 사항에 관심이있는 경우 ExitStack작동 방법을 설명하기위한 일반적인 예 는 다음과 같습니다.

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(len(stack._exit_callbacks)) # number of callbacks called on exit
    nums = [stack.enter_context(x) for x in xs]
    print(len(stack._exit_callbacks))

print(len(stack._exit_callbacks))
print(nums)

산출:

0
enter X1
enter X2
enter X3
3
exit X3
exit X2
exit X1
0
[1, 2, 3]

3

파이썬 2.6에서는 작동하지 않습니다. 여러 파일을 열려면 아래 방법을 사용해야합니다.

with open('a', 'w') as a:
    with open('b', 'w') as b:

1

늦은 답변 (8 세)이지만 여러 파일을 하나로 결합하려는 경우 다음 기능이 도움이 될 수 있습니다.

def multi_open(_list):
    out=""
    for x in _list:
        try:
            with open(x) as f:
                out+=f.read()
        except:
            pass
            # print(f"Cannot open file {x}")
    return(out)

fl = ["C:/bdlog.txt", "C:/Jts/tws.vmoptions", "C:/not.exist"]
print(multi_open(fl))

2018-10-23 19:18:11.361 PROFILE  [Stop Drivers] [1ms]
2018-10-23 19:18:11.361 PROFILE  [Parental uninit] [0ms]
...
# This file contains VM parameters for Trader Workstation.
# Each parameter should be defined in a separate line and the
...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.