Python 可选重定向I/O的上下文管理器
我经常遇到这样的情况,根据某些命令行参数,输入可能来自文件或标准输入。输出也是如此。我非常喜欢Python3中上下文管理器的工作方式,因此我尝试将所有Python 可选重定向I/O的上下文管理器,python,python-3.x,stdin,with-statement,contextmanager,Python,Python 3.x,Stdin,With Statement,Contextmanager,我经常遇到这样的情况,根据某些命令行参数,输入可能来自文件或标准输入。输出也是如此。我非常喜欢Python3中上下文管理器的工作方式,因此我尝试将所有打开调用作为一些with语句的一部分。但在这种情况下,我遇到了麻烦 if args.infile: with open(args.infile, "r") as f: process(f) else: process(sys.stdin) 它已经很笨拙了,而且在输入和输出方面,我必须满足四种组合。我想要更简单的,例
打开调用作为一些with
语句的一部分。但在这种情况下,我遇到了麻烦
if args.infile:
with open(args.infile, "r") as f:
process(f)
else:
process(sys.stdin)
它已经很笨拙了,而且在输入和输出方面,我必须满足四种组合。我想要更简单的,例如
with (open(args.infile, "r") if args.infile
else DummyManager(sys.stdin)) as f:
process(f)
python标准库中是否有类似于DummyManager的东西?实现上下文管理器协议,但仅从其\uuuuuu enter\uuuuu
方法返回固定值的东西?我想这样一个类最有可能的位置是,因为我没有在那里找到类似的东西,也许根本没有这样的东西。您还可以推荐其他优雅的解决方案吗?创建一个包含以下内容的解决方案非常简单:
就这样,;这将创建一个上下文管理器,它只将ob
返回给您,而\uuuu退出\uuuu
处理程序完全不执行任何操作
我会这样使用它:
f = open(args.infile, "r") if args.infile else dummy_manager(sys.stdin)
with f:
process(f)
在你的情况下,你不需要一个假经理sys.stdin
,类似于文件,可以用作上下文管理器
with (open(args.infile, "r") if args.infile else sys.stdin) as f:
process(f)
需要注意的一点是,当退出块时,sys.stdin会关闭(虽然您通常不需要/不想自己关闭),但这应该不是问题 在您的情况下,您可以使用:
如果args.infle='-'
则使用sys.stdin
。如果inplace=True
参数,则它将sys.stdout
重定向到输入文件。您可以传递几个文件名。如果没有文件名,则使用命令行或stdin中给定的文件名
或者您可以将文件保持原样:
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
对于大多数可以使用stdout编写结果的程序来说,这应该是好的
要避免关闭sys.stdin/sys.stdout
,可以使用有条件地启用上下文管理器:
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)
现在存在各种各样的ArgParse
包装器和替换,它们很好地支持这一点。我喜欢:
如果filename
是-
,这将处理sys.stdin
,否则会返回到常规的open
,在上下文管理器的部分最后隐藏一个close
。这适用于Python 2.7-FileInput()
直到3.2才获得上下文管理器的支持。
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
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)
with click.open_file(filename) as lines:
for line in lines:
process(line)