【问题标题】:Non-blocking read on subprocess output without flush() and new line没有flush()和新行的子进程输出的非阻塞读取
【发布时间】:2018-08-10 19:47:25
【问题描述】:

我有一个无法修改的程序。该程序将数据打印到stdout而不刷新它或将\n放入其中并等待输入等等。

我的问题是如何从 Python 脚本实时打印stdout 并写入他的stdin?我找到了一些方法可以在不关闭程序的情况下写入他的stdin,但打印他的stdout 的问题仍然存在。

事实上,线程存在一些问题,Popenfcntl 实时打印他的输出,但他们都假设程序在每次打印后刷新 stdout 并在其输出中包含 \n

为了清楚起见,假设我有一个程序test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void)
{
    char name[100], age[100], location[100];
    fprintf (stdout, "\nWhat is your name : ");
    fgets (name, sizeof (name), stdin);
    name[strcspn (name, "\n")] = '\0';
    fprintf (stdout, "How old are you : ");
    fgets (age, sizeof (age), stdin);
    age[strcspn (age, "\n")] = '\0';
    fprintf (stdout, "Where do you live : ");
    fgets (location, sizeof (location), stdin);
    location[strcspn (location, "\n")] = '\0';
    fprintf (stdout, "\nHello %s, you have %s years old and live in 
             %s\n\n", name, age, location);
    return 0;
}

我怎样才能从 Python 脚本中输出第一个 fprintf() 然后将答案写入他的标准输入等等,就像我可以简单地启动 test.c 一样?

目的是控制从脚本发送到该程序的数据,并且仍然可以返回所发生的事情。

【问题讨论】:

  • 这进入了不可移植的坏境(至少可能如此)。您需要在哪些操作系统上运行您的代码。
  • 对不起,这是针对 Linux 的

标签: python subprocess stdout stdin nonblocking


【解决方案1】:

您可以使用以下严重依赖标准 Python 语言的 subprocess 包的程序:

def run_program(cmd, sinput=''):
    """Run the command line and output (ret, sout, serr)."""
    import subprocess

    proc =  subprocess.Popen(cmd,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    sin = proc.stdin
    sout, serr = proc.communicate(sinput.encode("utf-8"))
    ret = proc.wait()

    return (ret, sout, serr)

所以,你刚刚用 C 编写的程序会给出以下内容:

cmd = ['myprogram']
sinput = 'myname\n6\nWhitechapel\n'
(ret, sout, serr) = run_program(cmd, sinput)

请注意,您不能仅仅因为您的目标程序使用它来知道您发送问题的答案而避免使用 \n 字符。

【讨论】:

  • 我想这是可能的,使用pty(也许tty)。既然普通终端可以做到,那么 Python 也应该做到这一点,前提是正确的 termios 设置。
  • 正确,但在复杂性方面过度杀伤(您必须寻找正确的 pty/tty 以链接到您的流程)。你不觉得吗?
  • 不,你会让 Python 创建一个新的 pty,使用来自 pty 模块的东西,例如pty.openpty()。但是你需要修复终端设置。而且,由于我目前不是 linux,因此无法对其进行测试并使其正常工作。
猜你喜欢
  • 1970-01-01
  • 2014-03-29
  • 2017-12-30
  • 1970-01-01
  • 2016-07-28
  • 2014-03-23
  • 2016-03-14
  • 2012-01-18
  • 1970-01-01
相关资源
最近更新 更多