如何在不编写额外代码的情况下使用 Python 将“-”(破折号)读取为标准输入?
How to read "-" (dash) as standard input with Python without writing extra code?
使用 Python 3.5.x,没有比那个更高的版本。
是正确的答案,但没有提供内置于 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 -
的方式将参数传递给脚本,表示 "read from standard-input" 或 -p some_text_file
表示 "read from some_text_file"。
这是否需要我执行上述操作,或者 Python 3.5.x 中是否已经内置了某些功能?这似乎是编写 CLI 实用程序的常见需求,它可能已经被 Python 核心或标准库中的某些东西处理了。
我不想从 3.Python 标准库之外的存储库安装任何 module/package。5.x,就是为了这个。
检查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)
因此 infile
& outfile
将默认支持 stdin
& stdout
的读写流。
或者使用我最喜欢的库 click
在图书馆文档网站上查看更多详细信息
https://click.palletsprojects.com/en/7.x/api/#click.File
https://click.palletsprojects.com/en/7.x/arguments/#file-arguments
File Arguments
Since all the examples have already worked with filenames, it makes sense to explain how to deal with files properly. Command line tools are more fun if they work with files the Unix way, which is to accept -
as a special file that refers to stdin/stdout.
Click supports this through the click.File type which intelligently handles files for you. It also deals with Unicode and bytes correctly for all versions of Python so your script stays very portable.
图书馆是我认为最“BASH/DASH”功能友好的。
argparse
模块提供了一个 FileType
工厂,它知道 -
约定。
import argparse
p = argparse.ArgumentParser()
p.add_argument("-p", type=argparse.FileType("r"))
args = p.parse_args()
注意args.p
是一个打开的文件句柄,所以不需要打开它"again"。虽然您仍然可以将它与 with
语句一起使用:
with args.p:
for line in args.p:
...
这只能确保在 with
语句本身出现错误时关闭文件。此外,您可能不想使用 with
,因为这会关闭文件,即使您打算稍后再次使用它也是如此。
您可能应该使用 atexit
模块来确保文件在程序结束时关闭,因为它已经在开始时为您打开。
import atexit
...
args = p.parse_args()
atexit.register(args.p.close)
使用 Python 3.5.x,没有比那个更高的版本。
我需要一个值为“-”的字符串来表示标准输入,或者它的值是我要读取的文本文件的路径。我想使用 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 -
的方式将参数传递给脚本,表示 "read from standard-input" 或 -p some_text_file
表示 "read from some_text_file"。
这是否需要我执行上述操作,或者 Python 3.5.x 中是否已经内置了某些功能?这似乎是编写 CLI 实用程序的常见需求,它可能已经被 Python 核心或标准库中的某些东西处理了。
我不想从 3.Python 标准库之外的存储库安装任何 module/package。5.x,就是为了这个。
检查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)
因此 infile
& outfile
将默认支持 stdin
& stdout
的读写流。
或者使用我最喜欢的库 click
在图书馆文档网站上查看更多详细信息
https://click.palletsprojects.com/en/7.x/api/#click.File https://click.palletsprojects.com/en/7.x/arguments/#file-arguments
File Arguments
Since all the examples have already worked with filenames, it makes sense to explain how to deal with files properly. Command line tools are more fun if they work with files the Unix way, which is to accept
-
as a special file that refers to stdin/stdout.Click supports this through the click.File type which intelligently handles files for you. It also deals with Unicode and bytes correctly for all versions of Python so your script stays very portable.
图书馆是我认为最“BASH/DASH”功能友好的。
argparse
模块提供了一个 FileType
工厂,它知道 -
约定。
import argparse
p = argparse.ArgumentParser()
p.add_argument("-p", type=argparse.FileType("r"))
args = p.parse_args()
注意args.p
是一个打开的文件句柄,所以不需要打开它"again"。虽然您仍然可以将它与 with
语句一起使用:
with args.p:
for line in args.p:
...
这只能确保在 with
语句本身出现错误时关闭文件。此外,您可能不想使用 with
,因为这会关闭文件,即使您打算稍后再次使用它也是如此。
您可能应该使用 atexit
模块来确保文件在程序结束时关闭,因为它已经在开始时为您打开。
import atexit
...
args = p.parse_args()
atexit.register(args.p.close)