2014-04-25 6 views
4

일부 명령 줄 인수에 따라 입력이 파일 또는 표준 입력에서 오는 경우가 종종 있습니다. 출력도 마찬가지입니다. 나는 파이썬 3의 컨텍스트 관리자가 어떻게 작동 하는지를 정말로 좋아한다. 따라서 모든 내 open 호출을 with 문으로 호출하려고한다. 하지만이 경우에는 문제가 있습니다.리디렉션 된 I/O에 대한 컨텍스트 관리자

if args.infile: 
    with open(args.infile, "r") as f: 
     process(f) 
else: 
    process(sys.stdin) 

은 이미 서투른 상태이며 입력과 출력 모두 4 가지 조합을 제공해야합니다. 나는 더 쉬운 것을 원한다.

with (open(args.infile, "r") if args.infile 
     else DummyManager(sys.stdin)) as f: 
    process(f) 

이 DummyManager와 비슷한 것이 Python 표준 라이브러리에 있습니까? 컨텍스트 관리자 프로토콜을 구현하는 것이지만 __enter__ 메서드에서 고정 값을 반환하는 경우에만 사용할 수 있습니까? 나는 그런 클래스를위한 가장 가능성있는 위치가 contextlib 일 것이라고 추측한다. 그리고 내가 이것과 같은 것을 발견하지 못했기 때문에 아마도 그런 것은 없다. 추천할만한 다른 우아한 솔루션이 있습니까?

답변

2

, 당신은 fileinput module을 사용할 수 있습니다 다음은 sys.stdin를 사용

from fileinput import FileInput 

with FileInput(args.infile) as file: 
    process(file) 
# sys.stdin is still open here 

args.infile='-'합니다. inplace=True 매개 변수 인 경우 sys.stdout을 입력 파일로 리디렉션합니다. 여러 개의 파일 이름을 전달할 수 있습니다. 파일 이름이 없으면 명령 행이나 표준 입력에서 주어진 파일 이름을 사용합니다.

또는 같이 파일을 떠날 수 :

import sys 
import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('--log', default=sys.stdout, type=argparse.FileType('w')) 
args = parser.parse_args() 
with args.log: 
    args.log.write('log message') 
# sys.stdout may be closed here 

그것은 표준 출력은 결과를 작성하는 데 사용할 수 있습니다 대부분의 프로그램 잘해야한다. sys.stdin/sys.stdout을 닫는 방지하기 위해

, 조건부 컨텍스트 관리자를 활성화 ExitStack을 사용할 수 있습니다 : 이것은 파이썬 2.7 `FileInput와 함께 작동

from contextlib import ExitStack 

with ExitStack() as stack: 
    if not args.files: 
     files = [sys.stdin] 
    else: 
     files = [stack.enter_context(open(name)) for name in args.files] 

    if not args.output: 
     output_file = sys.stdout 
     stack.callback(output_file.flush) # flush instead of closing 
    else: 
     output_file = stack.enter_context(open(args.output, 'w')) 

    process(files, output_file) 
2

그것은 @contextlib.contextmanager decorator 하나 만들 사소한 : 그것 뿐이다

from contextlib import contextmanager 

@contextmanager 
def dummy_manager(ob): 
    yield ob 

을; 이것은 ob을 돌려주는 context manager를 생성하고, __exit__ handler는 정확히 아무것도하지 않습니다.

나는이처럼 사용하십시오 : 당신은 당신의 경우 더미 관리자가 필요하지 않습니다

f = open(args.infile, "r") if args.infile else dummy_manager(sys.stdin) 
with f: 
    process(f) 
+0

을()'3.2까지 컨텍스트 매니저 지원을 얻을하지 않았다. –

1

. sys.stdin은 파일과 유사하며 컨텍스트 관리자로 사용할 수 있습니다. 주의 할

with (open(args.infile, "r") if args.infile else sys.stdin) as f: 
    process(f) 

한 가지 __exit__이 블록을 보내고 때, sys.stdin가 close D를 얻을 수 있다는 점이다 (당신은 일반적으로 스스로를 닫으려면/필요는 없지만),하지만 그건 문제가되지 않습니다. 귀하의 경우에는

관련 문제