【问题标题】:python: confusion when input is coming from a pipepython:输入来自管道时的混乱
【发布时间】:2021-08-27 03:21:57
【问题描述】:

我的python脚本可以在两种模式下使用:

./foo arg file

cat file | foo arg

这是我决定标准输入是否是管道的方式:

if sys.stdin.isatty():
    print('not pipe\n')
else:
    print('is pipe')

它的行为符合预期:

./foo arg file
not pipe

cat file | ./foo arg
is pipe

但是,在以下用法中,它认为输入来自管道,即使管道只是 while 循环的一部分:

while read F ; do foo arg $F ; done < /tmp/zz
is pipe

我将我的脚本称为./foo arg file。为什么它认为输入是管道?

【问题讨论】:

    标签: python shell while-loop stdin


    【解决方案1】:
    while read F ; do foo arg $F ; done < /tmp/zz
    

    您正在从/tmp/zz 重定向while 循环的标准输入(我假设这是一个文件)。这不仅包括条件测试中的read,还包括循环体中的所有语句(当然,除非它们被重定向)。

    您的 python 代码仅测试标准输入是否为 tty/终端,否则假设它是管道。但是标准输入可以来自任何类型的可以读取的打开文件描述符; tty、管道、常规文件、套接字等

    接受文件名和标准输入作为程序数据的典型方法是查看命令行参数的数量;如果它需要文件名,但没有足够的参数,请改为从标准输入中读取。


    如果使用bashzsh(可能还有其他扩展基本POSIX sh 的shell),如果您想在这样的循环中使用从脚本的原始标准输入读取的程序,一种技术是重定向到 不同 描述符而不是 0(标准输入)并告诉 read 改为从中读取:

    while read -r -u 3 f; do foo arg "$f" ; done 3< /tmp/zz
    

    打开文件 /tmp/zz 作为描述符编号 3。

    【讨论】:

    • 谢谢,但是键入复杂的结构来重定向到不同的描述符会很乏味。有没有办法在我的 python 代码中检测到这一点?另外,请不要说我不能使用参数的数量作为输入是否是管道的决定因素。如果用户使用错误数量的参数调用,这将导致混乱。
    • @400theCat 肯定会在程序中的某个地方确定您是从stdin 还是文件中读取。你不能把那个决定的结果保存在某个地方吗?
    【解决方案2】:

    您的想法在 stdin 未绑定到 TTY 的上下文中行不通,但您仍然不在管道中。

    在您的具体情况下,我将简单地从 file 参数的存在与否得出,无论是否从标准输入读取。

    【讨论】:

    • 我不能使用参数的数量作为输入是否是管道的决定因素。如果用户使用错误数量的参数调用,这将导致混乱。
    • ???然后你必须依靠启发式:如果最后一个参数是一个有效的文件名,把它当作一个文件;否则从 STDIN 读取。然而,整个事情对我来说就像一个定义错误的用户界面。另一种可能,被许多程序采用:取一个由单个破折号(-)组成的参数来表示这不是一个文件,而是从这里的标准输入读取
    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 2017-08-02
    • 1970-01-01
    相关资源
    最近更新 更多