Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 可选重定向I/O的上下文管理器_Python_Python 3.x_Stdin_With Statement_Contextmanager - Fatal编程技术网

Python 可选重定向I/O的上下文管理器

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) 它已经很笨拙了,而且在输入和输出方面,我必须满足四种组合。我想要更简单的,例

我经常遇到这样的情况,根据某些命令行参数,输入可能来自文件或标准输入。输出也是如此。我非常喜欢Python3中上下文管理器的工作方式,因此我尝试将所有
打开
调用作为一些
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)