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

问题描述 投票:0回答:3

使用Python 3.5.x,没有比该版本更高的版本。

https://stackoverflow.com/a/30254551/257924是正确的答案,但没有提供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)

我计划通过类似-p -的参数将参数传递给脚本,以表示“从标准输入读取”或-p some_text_file表示“从some_text_file读取”。

这是否要求我执行上述操作,或者Python 3.5.x中是否已内置某些功能来提供此功能?这似乎是编写CLI实用程序的常见需求,它可能已经由Python核心或标准库中的某些东西处理过。

为此,我不想从3.5.x中的Python标准库之外的存储库中安装任何模块/软件包。

python stdin contextmanager
3个回答
0
投票

我认为您正在寻找argparse


0
投票

检查https://docs.python.org/3/library/argparse.html#filetype-objects

您可以在哪里这样做

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
...                     default=sys.stdin)
>>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
...                     default=sys.stdout)

因此infileoutfile默认将支持stdinstdout的读写流。

或使用我最喜欢的库click

在图书馆文档网站上查看更多详细信息

https://click.palletsprojects.com/en/7.x/api/#click.Filehttps://click.palletsprojects.com/en/7.x/arguments/#file-arguments

文件参数

由于所有示例都已使用文件名,因此解释如何正确处理文件是有意义的。如果命令行工具以Unix方式处理文件,则它们会更有趣,这是将-作为引用stdin / stdout的特殊文件。

Click通过click.File类型支持此功能,它可以为您智能处理文件。它还针对所有版本的Python正确处理Unicode和字节,因此您的脚本保持了可移植性。

我相信该库是最友好的“ BASH / DASH”功能。


0
投票

argparse模块提供了一个FileType工厂,它知道-约定。

import argparse

p = argparse.ArgumentParser()

p.add_argument("-p", type=argparse.FileType("r"))

args = p.parse_args()

请注意,args.p是一个打开的文件句柄,因此无需“再次”打开它。虽然您仍然可以将其与with语句一起使用:

with args.p:
    for line in args.p:
        ...

这仅确保在with语句本身发生错误的情况下关闭文件。另外,您可能不想使用with,因为这将关闭文件,即使您打算稍后再次使用它。

您可能应该使用atexit模块来确保文件在程序结束时被关闭,因为它已经在开始时为您打开了。

import atexit

...

args = p.parse_args()
atexit.register(args.p.close)
© www.soinside.com 2019 - 2024. All rights reserved.