나는 with
오늘 처음으로 파이썬 진술을 보았습니다. 나는 몇 달 동안 파이썬을 가볍게 사용했지만 그 존재를 알지 못했습니다! 다소 모호한 지위를 감안할 때 물어볼 가치가 있다고 생각했습니다.
with
사용하기 위해 설계된 파이썬 문장 은 무엇입니까 ?- 무엇을 위해 사용합니까?
- 내가 알아야 할 문제점이나 그 사용과 관련된 일반적인 반 패턴이 있습니까? 사용하는 것이 더 나은 경우
try..finally
는with
무엇입니까? - 왜 더 널리 사용되지 않습니까?
- 어떤 표준 라이브러리 클래스와 호환됩니까?
답변
-
: 나는 단지 완전성을 위해 추가 있도록이 이미 내 앞에 다른 사용자가 응답 한 것으로 판단
with
문 단순화 예외 처리를 소위 공통 준비 및 정리 작업을 캡슐화하여 상황에 맞는 관리자 . 자세한 내용은 PEP 343 에서 찾을 수 있습니다 . 예를 들어,open
명령문은 자체적으로 컨텍스트 관리자이므로 파일을 열고with
사용한 명령문 의 컨텍스트에서 실행되는 동안 파일을 열어 두고 컨텍스트를 떠나 자마자 닫습니다. 예외로 인해 또는 정기적 인 제어 흐름 중에 방치했는지 여부에 관계없이.with
문을 따라서와 유사한 방법으로 사용할 수 있습니다 RAII 패턴 ++ C에서 : 일부 자원에 의해 획득with
당신이with
문맥 을 떠날 때 -
일부 예는 다음을 사용하여 파일 열기
with open(filename) as fp:
하여 잠금을 획득with lock:
(여기서lock
인스턴스이다threading.Lock
). 의contextmanager
데코레이터를 사용하여 자체 컨텍스트 관리자를 구성 할 수도 있습니다contextlib
. 예를 들어, 현재 디렉토리를 일시적으로 변경 한 다음 원래 위치로 돌아 가야 할 때 자주 사용합니다.from contextlib import contextmanager import os @contextmanager def working_directory(path): current_dir = os.getcwd() os.chdir(path) try: yield finally: os.chdir(current_dir) with working_directory("data/stuff"): # do something within data/stuff # here I am back again in the original working directory
여기에 일시적으로 리디렉션 또 다른 예입니다
sys.stdin
,sys.stdout
및sys.stderr
다른 파일 핸들 나중에 복원을하기 :from contextlib import contextmanager import sys @contextmanager def redirected(**kwds): stream_names = ["stdin", "stdout", "stderr"] old_streams = {} try: for sname in stream_names: stream = kwds.get(sname, None) if stream is not None and stream != getattr(sys, sname): old_streams[sname] = getattr(sys, sname) setattr(sys, sname, stream) yield finally: for sname, stream in old_streams.iteritems(): setattr(sys, sname, stream) with redirected(stdout=open("/tmp/log.txt", "w")): # these print statements will go to /tmp/log.txt print "Test entry 1" print "Test entry 2" # back to the normal stdout print "Back to normal stdout again"
마지막으로, 임시 폴더를 만들어 컨텍스트를 떠날 때 정리하는 또 다른 예는 다음과 같습니다.
from tempfile import mkdtemp from shutil import rmtree @contextmanager def temporary_dir(*args, **kwds): name = mkdtemp(*args, **kwds) try: yield name finally: shutil.rmtree(name) with temporary_dir() as dirname: # do whatever you want
답변
두 가지 흥미로운 강의를 제안합니다.
1.with
문은 콘텍스트 관리자에 의해 정의 된 방식으로 블록의 실행을 포장하는 데 사용된다. 이를 통해 일반적인 try...except...finally
재사용 패턴을 캡슐화하여 편리하게 재사용 할 수 있습니다.
2.
다음과 같은 작업을 수행 할 수 있습니다.
with open("foo.txt") as foo_file:
data = foo_file.read()
또는
from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
do_something()
또는 (Python 3.1)
with open('data') as input_file, open('result', 'w') as output_file:
for line in input_file:
output_file.write(parse(line))
또는
lock = threading.Lock()
with lock:
# Critical section of code
3.
반 패턴이 보이지 않습니다. 파이썬으로
인용 인용 :
try..finally는 좋다. 와 함께하는 것이 좋습니다.
4.try..catch..finally
다른 언어의 문장
을 사용하는 프로그래머의 습관과 관련이 있다고 생각합니다 .
답변
Python with
문은 Resource Acquisition Is Initialization
C ++에서 일반적으로 사용되는 관용구 의 내장 언어 지원입니다 . 운영 체제 자원을 안전하게 확보하고 해제 할 수 있도록 고안되었습니다.
with
문은 범위 / 블록 내에서 자원을 만듭니다. 블록 내의 리소스를 사용하여 코드를 작성합니다. 블록이 종료되면 블록의 코드 결과에 관계없이 (즉, 블록이 정상적으로 종료되는지 또는 예외로 인해) 리소스가 완전히 해제됩니다.
with
명령문에 필요한 프로토콜을 준수하는 Python 라이브러리의 많은 리소스가 기본적으로 사용할 수 있습니다. 그러나 누구나 잘 문서화 된 프로토콜을 구현하여 with 문에서 사용할 수있는 리소스를 만들 수 있습니다. PEP 0343
파일, 네트워크 연결, 잠금 등과 같이 명시 적으로 포기해야하는 리소스를 응용 프로그램에서 얻을 때마다 사용하십시오.
답변
완성도를 높이기 위해 가장 유용한 유스 케이스를 추가하겠습니다 with
.
나는 많은 과학 계산을 수행하고 일부 활동 Decimal
에는 임의의 정밀 계산을 위해 라이브러리 가 필요합니다 . 내 코드의 일부에는 고정밀이 필요하고 대부분의 다른 파트에는 정밀도가 떨어집니다.
기본 정밀도를 낮은 숫자로 설정 한 다음 with
일부 섹션에 대해보다 정확한 답변을 얻는 데 사용 합니다.
from decimal import localcontext
with localcontext() as ctx:
ctx.prec = 42 # Perform a high precision calculation
s = calculate_something()
s = +s # Round the final result back to the default precision
나는 이것을 하이퍼 지오메트리 테스트와 함께 많이 사용합니다. 게놈 스케일 계산을 수행 할 때 반올림 및 오버플로 오류에주의해야합니다.
답변
반 패턴의 예 with
는 with
외부 루프 를 갖는 것이 더 효율적일 때 내부 루프 를 사용하는 것일 수 있습니다.
예를 들어
for row in lines:
with open("outfile","a") as f:
f.write(row)
vs
with open("outfile","a") as f:
for row in lines:
f.write(row)
첫 번째 방법은 파일을 열고 닫는 것입니다 row
. 두 번째 방법과 비교할 때 파일을 한 번만 열고 닫는 것과 비교하여 성능 문제가 발생할 수 있습니다.
답변
PEP 343- ‘with’문을 참조하십시오 . 끝에 섹션이 있습니다.
… try / finally 문의 표준 사용을 고려할 수 있도록하기 위해 Python 언어에 “with”라는 새 명령문이 있습니다.
답변
포인트 1, 2 및 3은 합리적으로 잘 설명되어 있습니다.
4 : 그것은 비교적 새롭고 python2.6 +에서만 사용 가능합니다 (또는 python2.5 사용 from __future__ import with_statement
)