bgo*_*odr 1 python stdin contextmanager
使用 Python 3.5.x,没有比这更高的版本。
/sf/answers/2117818601/是正确的答案,但没有提供内置于 Python 的解决方案,而是需要从头开始编写代码:
我需要一个值为“-”的字符串来表示标准输入,或者它的值是我想要读取的文本文件的路径。我想使用with运算符打开这些文件中的任何一种,而不使用条件逻辑来检查脚本中的“-”。我有一些有用的东西,但它似乎应该是内置在 Python 核心中的东西,而不需要我推出自己的上下文管理器,如下所示:
from contextlib import contextmanager
@contextmanager
def read_text_file_or_stdin(path):
"""Return a file object from stdin if path is '-', else read from path as a text file."""
if path == '-':
with open(0) as f:
yield f
else:
with open(path, 'r') as f:
yield f
# path = '-' # Means read from stdin
path = '/tmp/paths' # Means read from a text file given by this value
with read_text_file_or_stdin(path) as g:
paths = [path for path in g.read().split('\n') if path]
print("paths", paths)
Run Code Online (Sandbox Code Playgroud)
我计划通过诸如-p -“从标准输入-p some_text_file读取”或“从 some_text_file 读取”之类的方式将参数传递给脚本。
这是否需要我执行上述操作,或者 Python 3.5.x 中是否已经内置了一些功能已经提供了这些功能?这似乎是编写 CLI 实用程序的常见需求,它可能已经由 Python 核心或标准库中的某些内容处理。
我不想从 3.5.x 中 Python 标准库之外的存储库中安装任何模块/包,仅此而已。
该argparse模块提供了一个FileType了解-约定的工厂。
import argparse
p = argparse.ArgumentParser()
p.add_argument("-p", type=argparse.FileType("r"))
args = p.parse_args()
Run Code Online (Sandbox Code Playgroud)
请注意,这args.p是一个打开的文件句柄,因此无需“再次”打开它。虽然您仍然可以将它与with语句一起使用:
with args.p:
for line in args.p:
...
Run Code Online (Sandbox Code Playgroud)
这只能确保在with语句本身出错时关闭文件。此外,您可能不想使用with,因为这会关闭文件,即使您打算稍后再次使用它。
您可能应该使用该atexit模块来确保文件在程序结束时关闭,因为它在开始时已经为您打开了。
import atexit
...
args = p.parse_args()
atexit.register(args.p.close)
Run Code Online (Sandbox Code Playgroud)