zoukankan      html  css  js  c++  java
  • Python和其他进程的管道通信方式--popen和popen2的比较

    目前有一个查询程序 get_user_id 是用C写的,python需要调用这个程序:使用 get_user_id  "用户名" 可以得到输出: "ID0002451".
      
      在python中使用管道可以方便的调用这个进程并得到它的标准输出:
     
      get_user_id 是C写的,程序大概的框架如下:得到一个命令行参数,然后根据参数打印其相应的id:
     
     
    int main(int argc , char* args[]) 

        char * name = args[1] 
        printf("%s",getid(name) ); 

     
     
      
      python程序调用的片段如下:
     
        pipe = os.popen( "get_user_id " + "myname"
     
        user_id    = pipe.read() 
         
          pipe.close()
     
      python是这样调用get_user_id程序的。 首先python会启动一个子进程,然后读入子进程的标准输出,最后结束子进程。 这里的主要的开销是进程的启动和撤销,管道之间的通信是非常快的。
     
      如果get_user_id调用得不太频繁,则这种调用方式没有问题;若get_user_id调用得很频繁,以致它的性能成为了系统的瓶颈,这就有必要优化了。优化的方法是使得get_user_id子进程常驻内存,python父进程可以使用write/flush和readline的方法和子进程通信;程序结束时撤销子进程。
      
      进程常驻内存后,python只需要启动一次子进程就可以满足任意次的查询。不过带来的麻烦是get_user_id程序需要重写:将它改为在循环中接收标准输入,把结果送往标准输出,另外约定一个特殊的输入(如"EOF"),子进程收到这个输入后退出循环。
      
      get_user_id改后
      
     
    int main(int argc , char* args[]) 
          char name[512]; // buff
        while( scanf("%s", name)  ){
              if (!strcmp(name,"EOF")) return 0;
            printf("%s ",getid(name) ); 
          }

     
     
      
      这个C程序先接受标准输入,判断输入是否结束为结束标志,如果是则返回,否则打印用户ID。
      
      Python应该如何调用这个进程呢?使用popen()得到的pipe对象只支持write或者read操作,而不能同时读和写。
     
      需要同时允许读写操作,使用popen2()。该函数返回一个包涵两个元素的tuple,这两个元素依次是写管道(即可向目标进程写入标准输入)和读管道(即读进程的标准输出)。
      如果需要和上述C程序打交道,则应该这样打开管道
     
      pipe_out , pipe_in = popen2( " get_user_id " , "wr");
      
      "wr"表示次管道需要先写后读。
     
      具体例子如下:进行10000次查询
     
       
    import os 
     
    if __name__ == "__main__"
         
        pipe_in , pipe_out = popen2("get_user_id""wr"); 
        for i in range(10000) 
            pipe_in.write("myname"); 
            pipe_in.write(" "); #需要换行符
            pipe_in.flush(); #需要清空缓冲区
             
            userid = pipe_out.readline(); #读入结果
     
     
     上述情况需要注意的是,为了和进程顺利交互,一般需要flush,防止io缓冲;尽量写入和读入整行,方便控制管道交互过程。
     
     根据笔者试验显示:使用常驻内存的进程进行10000次调用,比不常驻内存的进程快得多,前者耗费的时间大约是后者的1/5,不过这个结果只是笔者的特例。请读者分析自己的应用场合,看看如何使用python强大的管道工具。
     
     ps,python还有popen3,可打开进程的stdin,stdout和stderr,更好更强大。另外subprocess 模块下有更强大的进程管理接口。
  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/jefree/p/4461989.html
Copyright © 2011-2022 走看看