【问题标题】:Read-write pipe() communication in RR中的读写管道()通信
【发布时间】:2011-07-18 08:05:36
【问题描述】:

大多数语言都支持双向进程通信。例如,在 Python 中,我可以(草率地)这样做:

>>> from subprocess import *
>>> p = Popen('nslookup', stdin=PIPE, stdout=PIPE)
>>> p_stdin, p_stdout = p.communicate("www.google.com")
>>> print p_stdin
Server:     ...

在 R 中,无论我是用“r+”还是“w+”打开管道,我似乎只能走一条路。此外,即使我通过R -f ...R < ... 运行脚本,实际控制台标准输入/标准输出中也会出现奇怪的行为。

我的问题归结为以下问题 - 是否有可能(不编写 C 方法!)在 R 中重现上述 Python 示例中的双向进程通信?

【问题讨论】:

    标签: r ipc pipe


    【解决方案1】:

    在类 UNIX 系统上执行此操作的一种方法是打开一个管道到将 stdoutstderr 重定向到 fifo 的进程:

    # Setup
    system('mkfifo output.fifo')
    p_out <- fifo('output.fifo', 'r')
    p_in <- pipe('pdflatex &> output.fifo', 'w')
    
    # See what TeX said on startup
    readLines(p_out)
    [1] "This is pdfTeX, Version 3.1415926-1.40.11 (TeX Live 2010)"
    
    readLines(p_out)
    character(0) # TeX has nothing more to say
    
    # Tell TeX to do something
    writeLines('\\documentclass{article}', p_in)
    flush(p_in)
    
    # See what it said in response
    readLines(p_out)
    [1] "**entering extended mode"                                                       
    [2] "LaTeX2e <2009/09/24>"                                                           
    [3] "Babel <v3.8l> and hyphenation patterns for english, dumylang, nohyphenation, ba"
    [4] "sque, danish, dutch, finnish, french, german, ngerman, swissgerman, hungarian, "
    [5] "italian, bokmal, nynorsk, polish, portuguese, spanish, swedish, loaded."        
    [6] ""
    

    很遗憾,fifo 在 Windows 上不受支持。

    【讨论】:

      【解决方案2】:

      很久以前,我还在Octave 中使用了双向管道,所以,是的,如果有这个就好了。但是细读help(pipe) 并不意味着这是支持。你会读写,但似乎不是两者兼而有之。

      但也许你可以作弊。打开管道以写入应用程序,您可以使用标准输出重定向到文件来调用该应用程序......然后继续读取该文件。但是,由于未刷新缓冲区,可能会一团糟。

      【讨论】:

      • 这是与 base 的平台兼容性问题吗?我应该在那里提交错误/问题吗?此外,文件选项在技术上是一种解决方案,但这实际上是用于管道大量 SQL 结果以避免出现错误的 ODBC 驱动程序,因此写入磁盘和读回会非常慢。
      • 我在 Linux 上试过,如果 R 支持它就会有它。除非您可以编写错误报告,或者花钱请人来做,否则提交错误报告是没有意义的——R Core 忙得不可开交。最后,我个人倾向于通过编写直接 DB 访问片段来避免错误的 ODBC 驱动程序。去过那里,通过一些 GSoC 指导为 Bloomberg、Lim、OneTick 和 PostgreSQL 等后端完成。你的后端是什么?
      • @mjbommar,我也没有找到一种方法来做你描述的事情,我花了几个小时尝试。但是,如果您只是想在不使用 ODBC 驱动程序的情况下将结果从 SQL DB 获取到 R 中,您可能不需要双向交互。尝试使用 system() 连接到它并将您的查询作为输入提供。我这样做是为了访问我所有的数据库(这需要 RMySQL 无法做到的 SSH 隧道)。
      • 另一边的数据库是 Vertica(遗憾的是 pgsql 客户端不起作用)。听起来我会继续使用我现在拥有的解决方案,即在前面调用带有 paste('echo', query, '|') 的 SQL 客户端,但 Dirk 的答案可能是大多数人的正确解决方案。我再给它几个小时然后接受它。
      【解决方案3】:

      可以像这样从 R 在 Jython 中运行该部分。加载java(发生在第二个语句中)会很慢,但之后应该没问题。

      library(rJython)
      
      .Jython <- rJython()
      
      jython.assign(.Jython, "x", "www.google.com")
      jython.exec(.Jython, "from subprocess import *
      p = Popen('nslookup', stdin=PIPE, stdout=PIPE)
      p_stdin, p_stdout = p.communicate(x)")
      
      cat(jython.get(.Jython, "p_stdin"), "\n\n")
      

      最后一条语句给出:

      > cat(jython.get(.Jython, "p_stdin"), "\n\n")
      Default Server:  UnKnown
      
      Address:  192.168.0.1
      
      
      
      > www.google.com 
      

      【讨论】:

      • 我投了赞成票,因为它可能对某些人有用,但这个选项对我的应用程序调用了太多开销。
      • @mbommar,您指的具体开销是多少?如果它的速度,那么唯一慢的部分是 .Jython &lt;- rJython() 语句(因为它加载了 JVM)并且只需要在会话开始时执行一次,因此它只会影响启动时间。如果需要考虑启动时间,那么我同意这将是一个问题。
      猜你喜欢
      • 2013-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多