with
파이썬 에서 명령문을 사용하여 둘 이상의 변수를 선언 할 수 있습니까?
다음과 같은 것 :
from __future__ import with_statement
with open("out.txt","wt"), open("in.txt") as file_out, file_in:
for line in file_in:
file_out.write(line)
… 또는 동시에 두 개의 리소스를 정리하는 것이 문제입니까?
답변
v3.1 및 Python 2.7 이후의 Python 3 에서 가능합니다 . 새로운 with
구문 은 여러 컨텍스트 관리자를 지원합니다.
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
는 달리 contextlib.nested
,이 보장 a
하고 b
있는 것은 __exit__()
‘경우에도라고 s의 C()
또는 그것의 __enter__()
메소드가 예외를 발생시킵니다.
나중에 정의 할 때 이전 변수를 사용할 수도 있습니다 ( 아래의 h / t Ahmad ).
with A() as a, B(a) as b, C(a, b) as c:
doSomething(a, c)
답변
contextlib.nested
이것을 지원합니다 :
import contextlib
with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):
...
업데이트 :
관련 문서를 인용하려면 contextlib.nested
:
버전 2.7부터 더 이상 사용되지 않음 : with-statement는 이제 혼란스러운 오류가 발생하지 않는이 기능을 직접 지원합니다.
자세한 내용은 Rafał Dowgird의 답변 을 참조하십시오.
답변
변수를 줄로 나누면 백 슬래시를 사용하여 줄 바꿈을 래핑해야합니다.
with A() as a, \
B() as b, \
C() as c:
doSomething(a,b,c)
파이썬이 대신 튜플을 생성하기 때문에 괄호가 작동하지 않습니다.
with (A(),
B(),
C()):
doSomething(a,b,c)
튜플에는 __enter__
속성이 없으므로 오류가 발생합니다 (설명 적이 지 않고 클래스 유형을 식별하지 못함).
AttributeError: __enter__
as
괄호 안에 사용하려고하면 파이썬은 구문 분석시 실수를 포착합니다.
with (A() as a,
B() as b,
C() as c):
doSomething(a,b,c)
SyntaxError : 유효하지 않은 구문
https://bugs.python.org/issue12782 는이 문제와 관련이있는 것 같습니다.
답변
나는 당신이 대신 이것을하고 싶다고 생각합니다.
from __future__ import with_statement
with open("out.txt","wt") as file_out:
with open("in.txt") as file_in:
for line in file_in:
file_out.write(line)
답변
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
일반적인 예는 다음과 같습니다.
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(stack._exit_callbacks)
nums = [stack.enter_context(x) for x in xs]
print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)
산출:
deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]
답변
Python 3.1 이상에서는 여러 컨텍스트 표현식을 지정할 수 있으며 여러 with
명령문이 중첩 된 것처럼 처리됩니다 .
with A() as a, B() as b:
suite
에 해당
with A() as a:
with B() as b:
suite
이는 또한 두 번째 표현식의 첫 번째 표현식에서 별명을 사용할 수 있음을 의미합니다 (db 연결 / 커서 작업시 유용함).
with get_conn() as conn, conn.cursor() as cursor:
cursor.execute(sql)