【问题标题】:shell: pipe file to python stdin and also display to screen外壳:管道文件到 python 标准输入并显示到屏幕
【发布时间】:2021-09-05 13:52:47
【问题描述】:

你好!这是我在 StackOverflow 上的第一个问题,如果我做错了什么,请指导我。

所以我有一个 python 脚本,我想制作一个 shell 脚本,以便在运行时将文本文件传送到 python。

问题是从文件管道到 python 的文本没有显示在屏幕上。

这是我尝试过的代码:

python3 index.py < input.txt

index.py

while True:
    x = input("Input: ")
    print("Input ->", x)

输入.txt:

Test1
Test2
Test3

在我尝试运行命令后,结果是:

Input: Input -> Test1
Input: Input -> Test2
Input: Input -> Test3
Input: Input ->
Input: Traceback (most recent call last):
  File "index.py", line 2, in <module>
    x = input("Input: ")
EOFError: EOF when reading a line

(忽略错误)

管道中的文本不显示。不仅如此,它甚至不显示新行。

很遗憾,这不是我想要的结果:(

这是我预期的结果:

Input: Test1
Input -> Test1
Input: Test2
Input -> Test2
Input: Test3
Input -> Test3
...

我已经尝试了以下命令:

cat input.txt | python3 index.py

结果如上。

这是我尝试的另一种方法:

cat input.txt | tee /dev/tty | python3 index.py

结果仍然不是我所期望的:

Test1
Test2
Test3

Input: Input -> Test1
Input: Input -> Test2
Input: Input -> Test3

我还通过启动一个分离的屏幕会话并通过-X stuff "Test1^M" 发送文本来查看屏幕命令,但问题是我不想制作一个类似于循环文本行并使用屏幕命令的 shell 脚本发送。 (我希望python尽可能快地读取标准输入)

纯shell脚本可以做到吗?

感谢您的进一步回答。

【问题讨论】:

  • 我认为 Input: Test1 中的 Test1 来自您在终端中输入的任何内容,如果是管道,input.txt 的输出将进入 index.py 的输入,而无需中间人提示,这就是它不打印的原因。
  • 关于一般指导,请拨打tour并阅读How to Ask。对于有问题的代码,请始终提供minimal reproducible example。也就是说,请查看您应用于问题的标签的描述。特别是“shell”有点无意义,“linux”根本不适用。

标签: python linux shell pipe


【解决方案1】:

您通过 管道 file-output 调用 Python-Script 的方式将不起作用,因为您是不处理脚本中任何已解析的参数。

看看:

https://docs.python.org/3/library/argparse.html

What's the best way to parse command line arguments?

【讨论】:

    【解决方案2】:

    这是我预期的结果:

    一般来说,一般情况下是不可能做到的。通常,要做到这一点,进程之间需要平均单向同步,以检测底层进程何时停止处理当前数据块并将这一事实传达给提供数据的进程。 | 管道中没有这样的同步。

    在这种情况下,您可以假设底层进程在写入换行符后停止处理数据。在这种情况下,您可以以同步的方式向进程发送一行数据并从进程接收一行数据。

    或者使用最差的同步方式——sleep。发送一个数据和sleep 1 秒,给进程提供了足够多的时间来处理当前数据包。

    纯shell脚本可以做到吗?

    是的。您可能想对 bash coproc-ceses、进程间同步、shell 中的管道和文件描述符以及缓冲模式(非缓冲、行缓冲和全缓冲)感兴趣。例如:

    coproc python3 index.py
    exec 10<&${COPROC[0]}
    exec 11>&${COPROC[1]}
    while IFS= read -r input; do
       printf "Sending: %s\n" "$input"
       # sending excatly one line of input
       printf "%s\n" "$input" >&11
       # synchronize input with ouput by waiting for one line
       if ! IFS= read -t 1 -r output <&10; then
           echo "The process failed to answer in one second"
       fi
       printf "Process answered: %s\n" "$output"
    done <<<$'Test1\nTest2\nTest3'
    exec 11>&-  # close input
    cat <&10    # flush whatever else there is
    exec 10<&-
    

    逐行发送,并在发送下一行之前期望进程的输出正好是一行。总的来说,“异步”是一个很难掌握的概念。

    请注意,python3 端的输出完全缓冲会中断同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 2014-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-16
      相关资源
      最近更新 更多