Python会接受破折号“-”作为`open()`函数的文件名参数以将输出写入标准输出吗?

3
我正在使用一个接受输出文件作为参数的Python脚本。它使用open(outfile, "w")打开并写入该文件。
Linux中的一种常见约定是使用-(破折号)将内容写入标准输出。这是一种常见的约定,但不是标准或shell的一部分。 我能否将-作为outfile名称传递,以便Python的open将内容写入标准输出?
4个回答

5
不,标准库中的open()函数没有将文件名'-'翻译成stdinstdout。它只是一个普通的文件名,所以open("-", "w")会将内容写入到当前工作目录下名为-的文件中。
你需要显式地测试该值,并返回sys.stdinsys.stdout(取决于你需要读取还是写入),而不是打开一个文件。
例如 click 命令行界面库,支持在命令行上使用 - 作为文件名,其明确在其 open_stream() 实现 中测试了文件名是否为 '-'(链接2)
if filename == '-':
    if any(m in mode for m in ['w', 'a', 'x']):
        if 'b' in mode:
            return get_binary_stdout(), False
        return get_text_stdout(encoding=encoding, errors=errors), False
    if 'b' in mode:
        return get_binary_stdin(), False
    return get_text_stdin(encoding=encoding, errors=errors), False

open()接受文件句柄,因此您可以传入0表示标准输入,或1表示标准输出:

>>> inp = open(0)
>>> inp
<_io.TextIOWrapper name=0 mode='r' encoding='UTF-8'>
>>> inp.read(1)  # read 1 character from stdin, I entered 'a'
a
'a'
>>> outp = open(1, 'w')
>>> outp
<_io.TextIOWrapper name=1 mode='w' encoding='UTF-8'>
>>> outp.write("foo!")  # line buffered, no newline written so not visible yet
4
>>> outp.flush()  # flush the buffer
foo!>>>

2

这取决于您如何检索命令行参数。使用sys.argv、argparse或OptionParser模块,您可以检索到“-”符号。但是在这种情况下,打开标准输出取决于您自己。


我所使用的脚本使用了 OptionParser https://docs.python.org/2/library/optparse.html - Freiheit

-1

你应该进行测试以确保,但根据Python文档:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

file是一个类似路径的对象,给出要打开的文件的路径名(绝对或相对于当前工作目录)或要包装的文件的整数文件描述符。 (如果给出文件描述符,则在关闭返回的I / O对象时关闭它,除非将closefd设置为False。)

类似路径的对象是表示文件系统路径的对象。 类似路径的对象是表示路径的str或bytes对象,或实现os.PathLike协议的对象。 支持os.PathLike协议的对象可以通过调用os.fspath()函数将其转换为str或bytes文件系统路径; os.fsdecode()和os.fsencode()分别可用于保证结果为str或bytes。由PEP 519引入。

所以,是的,它应该可以工作。

请参考https://docs.python.org/3/library/functions.html#openhttps://docs.python.org/3/glossary.html#term-path-like-object获取更多信息。

2
我尝试了一下,最终得到的文件名字实际上是一个连字符(dash)“-”,并且对应的权限为 -rw-rw-r-- 1 user group 232M Nov 20 15:25 -。我认为sys.stdout 是一个类似于文件对象的东西,但是我觉得我不能将它作为一个参数传递。 - Freiheit
2
这并没有说明它是否受支持。由于“ - ”不是有效的文件名,因此它不受支持。 - Martijn Pieters
谢谢你们的解释,我也不太确定。 - Croves
2
@MartijnPieters,...嗯?在UNIX上,“-”是一个完全有效的文件名(评估为当前目录中命名为“-”的文件),尽管OP正在询问他们是否可以使用该名称来获取stdout的句柄;据我所知,您的答案是唯一正确且切题的,因此我的争论只是针对评论。 - Charles Duffy
1
@CharlesDuffy 是的,我表达不够准确。这是一个有效的文件名,但并不意味着它应该被用作文件名。在这里,它是一种共生名称。 - Martijn Pieters

-2

在Linux Mint 19 (Python 3.6)上测试过,似乎没有问题。但是文件名中应避免使用以下字符:

\ / : * ? " < > |

其中一些字符在Linux上实际上可以正常工作,但为什么要牺牲可移植性呢?


1
OP不想打开一个文件名为破折号的文件,他们想要打开stdout(因为UNIX上的许多工具将单个破折号视为对现有stdin或stdout FD的引用,具体取决于打开是读还是写)。关于文件名的建议完全是无关紧要的。 - Charles Duffy
我已经重新阅读了OP的帖子,很明显他们正在询问open('-', 'w')是否打开stdout,而不是它是否可以用于打开名为“-”的文件。 - Charles Duffy
顺便说一下,在传统的类Unix系统中,除了“/”和NUL字符之外的每个字符都是文件名有效的(当然,“/”在完全限定路径中是有效的,因此可以准确地说,在UNIX上,NUL是文件名中唯一无效的字符)。不过这并不是重点,OP根本没有询问有关有效文件名的问题,而是询问是否需要特殊处理将作为文件名传递给他们脚本的“-”解析为适当的sys.stdinsys.stdout;他们对其他答案的评论以及所选择的接受答案的选择更加清晰明了。 - Charles Duffy
@CharlesDuffy,你真快。抱歉,我之前的评论已经删除了,只有在浏览器刷新后才意识到你已经回答了。 - EK1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接