同时读/写python子流程.Popen

2024-09-28 23:01:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的C程序,它的工作方式如下: 征求意见 打印出来 询问其他输入 再次打印

现在我用python调用这个程序。在

import subprocess

sobj = subprocess.Popen("./cprog", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
sobj.stdin.write("2 3\n")
sobj.stdin.close()
sobj.stdout.read()

这个很好用。同样与沟通其工作良好。在

但当我试图做这样的事情时,它是行不通的

^{pr2}$

以下是几点: 1我看到了pexpect,但我认为我们应该提前给出程序要求的内容。 2我可以重新打开关闭的子流程管道吗?在

我用上面的脚本作为CGI,我不知道为什么但是subprocess.call那样不行。有人能解释一下为什么吗?在

编辑:

<>我做了一个基于Web的项目,用户在C、C++或java中编写代码,并在浏览器上执行它们。所以首先我想用PHP来实现它,但是我找不到一种方法来调用程序并以交互方式运行它们。然后我看到了python子进程模块。当我用翻译的时候,一切都很好subprocess.call. 但是同一个python程序保存为.cgi并在浏览器中打开它时却不起作用。然后我开始看子流程.popen. 但是我需要在开始时给出所有的输入,然后运行代码。我想做的是在浏览器中运行一个交互式会话。在

编辑2: 所以我想要的是用户在浏览器中运行程序,并在需要时在提供的文本框中输入输入,然后将输入重定向到子进程的stdin并基于其输出。在

编辑3:cprog.c

 #include <stdio.h>
 int main() {
   int x;
   printf("Enter value of x: \n");
   scanf("%d", &x);
   printf("Value of x: %d\n", x);
   return 0;
 }

Tags: 代码用户程序编辑进程stdinstdout浏览器
2条回答

When I run C program directly through terminal its working fine. But when I run the same program with 2nd code i provided above nothing prints.

您看不到任何输出的原因是,当程序在非交互模式下运行时,C stdio使用块缓冲。见my answer that demonstrate several solutions: ^{}, ^{}, ^{}。如果您可以更改C代码,那么您也可以fflush the output explicitly or make it unbuffered。在

如果您可以一次提供所有输入,并且输出是有界的,那么您可以使用.communicate()

from subprocess import Popen, PIPE

p = Popen(["./cprog"], stdin=PIPE, stdout=PIPE, stderr=PIPE,
          universal_newlines=True)
out, err = p.communicate("2\n")

So what I want is user runs program in browser and enters input in textbox provided whenever needed and that input is redirected to stdin of subprocess and output based on it.

基于ws-cli example

^{pr2}$

其中index.html

<!doctype html>
<title>Send input to subprocess using websocket and echo the response</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js">
</script>
<script>
// send keys to websocket and echo the response
$(document).ready(function() {
    // create websocket
    if (! ("WebSocket" in window)) WebSocket = MozWebSocket; // firefox
    var socket = new WebSocket("ws://localhost:8076");

    // open the socket
    socket.onopen = function(event) {
    // show server response
    socket.onmessage = function(e) {
        $("#output").text(e.data);
    }

    // sent input
    $("#entry").keyup(function (e) {
        socket.send($("#entry").attr("value")+"\n");
    });
    }
});
</script>
<pre id=output>Here you should see the output from the command</pre>
<input type=text id=entry value="123">

cprog.c

#include <stdio.h>
int main() {
  int x = -1;
  setbuf(stdout, NULL); // make stdout unbuffered

  while (1) {
    printf("Enter value of x: \n");
    if (scanf("%d", &x) != 1)
        return 1;
    printf("Value of x: %d\n", x);
  }
  return 0;
}

我假设您的C应用程序显示一个提示,并希望用户在同一行输入他们的输入,并且在上面的readline()调用中,您试图获得提示。在

如果是这种情况,readline()将永远阻塞,因为它正在等待换行符,而从未看到它。如果您将这个调用转换为一个简单的read(X)(其中X是一次读取的字节数),那么您可能会有更好的运气,尽管您应该处理部分输入(即循环收集输入,直到您看到整个提示)。您可能看到的另一个问题是C应用程序是否在提示用户之前刷新输出,但是如果是这样的话,我希望您在交互会话中也能看到这个问题。在

当在像Apache这样的web服务器环境下运行时,使用subprocess这样的东西通常是个坏主意,因为它们涉及到派生额外的进程,这通常是一件非常棘手的事情。这是因为fork进程复制了父进程的大部分状态,有时这会导致问题。我不是说它行不通,我只是说如果你不小心,你会给自己制造一些微妙的问题,如果这就是你在使用subprocess时遇到麻烦的原因,我也不会感到惊讶。在

不过,为了提供更多有用的建议,您需要准确描述调用子流程时看到的错误。例如,很有可能会抛出一个异常,它可能会出现在您的web服务器日志中,在这里重现这个异常将是一个很好的开始。在

相关问题 更多 >