c – 子进程的异步双向IO重定向

c – 子进程的异步双向IO重定向,第1张

概述我试图找出子进程的异步双向IO重定向的通用方法.基本上,我想生成一个等待输入的交互式子进程,应该回读任何输出.我尝试通过生成一个新的 python进程来试验 python.subprocess.试图实现的基本简化示例如下 process = subprocess.Popen(['/usr/bin/python'],shell=False,stdin=subprocess.PIPE, stdout= 我试图找出子进程的异步双向IO重定向的通用方法.基本上,我想生成一个等待输入的交互式子进程,应该回读任何输出.我尝试通过生成一个新的 python进程来试验 python.subprocess.试图实现的基本简化示例如下

process = subprocess.Popen(['/usr/bin/python'],shell=False,stdin=subprocess.PIPE,stdout=subprocess.PIPE)while True:    output = process.stdout.readline()    print output    input = sys.stdin.readline()    process.stdin.write(input)

执行上面的代码片段只是挂起而没有任何输出.我尝试使用/usr/bash和/usr/bin/irb运行,但结果完全相同.我的猜测是,缓冲的IO根本不适合IO重定向.

所以我的问题是,在不刷新缓冲区或退出子进程的情况下读取子进程的输出是否可行?

following post提到了IPC插座,但为此我必须改变儿童过程,这可能是不可行的.有没有其他方法可以实现它?

注意***我的最终目标是创建一个可以与远程Web客户端交互的服务器REPL过程.虽然给出的示例是Python,但我的最终目标是通过通用包装器包装所有可用的REPL.

在答案的一些建议的帮助下,我想出了以下内容

#!/usr/bin/pythonimport subprocess,os,selectproc = subprocess.Popen(['/usr/bin/python'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)for i in xrange(0,5):    inputready,outputready,exceptready = select.select([proc.stdout,proc.stderr],[proc.stdout,0)    if not inputready: print "No Data",print inputready,exceptready    for s in inputready: print s.fileno(),s.readline()proc.terminate()print "After Terminating"for i in xrange(0,s.readline()

现在,虽然程序没有陷入僵局,但不幸的是没有输出.运行上面的代码我得到了

No Data [] [] []No Data [] [] []No Data [] [] []No Data [] [] []No Data [] [] []After TerminatingNo Data [] [] []No Data [] [] []No Data [] [] []No Data [] [] []No Data [] [] []

仅供参考,
像运行python一样

/usr/bin/python 2>&1|tee test.out

似乎工作得很好.

我还想出了一个’C’代码.但结果并没有什么不同.

int kbhit() {    struct timeval tv;    fd_set fds;    tv.tv_sec = tv.tv_usec = 0;    FD_ZERO(&fds);    FD_SET(STDIN_fileNO,&fds);    select(STDIN_fileNO+1,&fds,NulL,&tv);    return FD_ISSET(STDIN_fileNO,&fds);}voID receive(char *str) {    char ch;    fprintf(stderr,"IN1\n");    if(!kbhit()) return;    fprintf(stderr,"IN2\n");    fprintf(stderr,"%d\n",kbhit());    for(;kbhit() && (ch=fgetc(stdin))!=EOF;) {        fprintf(stderr,"%c,%d",ch,kbhit());    }    fprintf(stderr,"Done\n");}int main(){    pID_t pID;    int rv,pipeP2C[2],pipeC2P[2];      pipe(pipeP2C);    pipe(pipeC2P);    pID=fork();    if(pID){        dup2(pipeP2C[1],1); /* Replace stdout with out sIDe of the pipe */        close(pipeP2C[0]);  /* Close unused sIDe of pipe (in sIDe) */        dup2(pipeC2P[0],0); /* Replace stdin with in sIDe of the pipe */        close(pipeC2P[1]);  /* Close unused sIDe of pipe (out sIDe) */        setvbuf(stdout,(char*)NulL,_IONBF,0);   /* Set non-buffered output on stdout */        sleep(2);        receive("quit()\n");        wait(&rv);              /* Wait for child process to end */        fprintf(stderr,"Child exited with a %d value\n",rv);    }    else{        dup2(pipeP2C[0],0); /* Replace stdin with the in sIDe of the pipe */        close(pipeP2C[1]);  /* Close unused sIDe of pipe (out sIDe) */        dup2(pipeC2P[1],1); /* Replace stdout with the out sIDe of the pipe */        close(pipeC2P[0]);  /* Close unused sIDe of pipe (out sIDe) */        setvbuf(stdout,0);   /* Set non-buffered output on stdout */        close(2),dup2(1,2); /*Redirect stderr to stdout */        if(execl("/usr/bin/python","/usr/bin/python",NulL) == -1){            fprintf(stderr,"execl Error!");            exit(1);        }    }    return 0;}
解决方法 在您发布的Python代码中,您没有使用正确的流:

inputready,exceptready = select.select(    [proc.stdout,# read List    [proc.stdout,# write List    [proc.stdout,# error List.    0)                          # time out.

我没有尝试修复它,但我打赌阅读和写入同一组流是不正确的.

您的样本中有多个问题.第一个是你作为子进程启动的python可执行文件不产生输出.第二个是存在竞争条件,因为您可以在子进程生成输出之前连续5次调用select(),在这种情况下,您将在读取任何内容之前终止该进程.

我解决了上面提到的三个问题(写清单,启动产生输出和竞争条件的过程).试试这个样本,看看它是否适合你:

#!/usr/bin/pythonimport subprocess,select,timepath = "/usr/bin/python"proc = subprocess.Popen([path,"foo.py"],5):    time.sleep(1)    inputready,exceptready = select.select(        [proc.stdout,[proc.stdin,],proc.stderr,proc.stdin],0)    if not inputready:        print "No Data",exceptready    for s in inputready:        print s.fileno(),s.readline()proc.terminate()print "After Terminating"for i in xrange(0,s.readline()

我使用的foo.py文件包含:

#!/usr/bin/pythonprint "Hello,world!"

以下版本(主要删除了冗余输出以使结果更易于阅读):

#!/usr/bin/pythonimport subprocess,0)    for s in inputready:        line = s.readline()        if line:            print s.fileno(),lineproc.terminate()print "After Terminating"for i in xrange(0,line

给出以下输出:

5 Hello,world!

After Terminating

请注意,由于某些原因,在select.select()中使用timeout参数并未在我的系统上产生预期的结果,而是使用time.sleep()代替.

Just FYI,running python as

06004

seems to be working just fine.

你不能得到这种效果,因为这个例子仍然给python解释器一个控制tty.没有控制tty,python解释器不会打印Python版本,也不会显示>>>提示.

一个接近的例子如下.您可以将/ dev / null替换为包含要发送到解释器的命令的文件.

/usr/bin/python </dev/null 2>&1|tee test.out

如果您将控制tty(键盘)以外的任何内容重定向到进程的标准输入,则不会从python解释器获得任何输出.这就是您的代码似乎不起作用的原因.

总结

以上是内存溢出为你收集整理的c – 子进程的异步双向IO重定向全部内容,希望文章能够帮你解决c – 子进程的异步双向IO重定向所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1230002.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存