如何在不编写额外代码的情况下使用 Python 将“-”(破折号)作为标准输入读取?

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 标准库之外的存储库中安装任何模块/包,仅此而已。

che*_*ner 5

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)