2011-03-18 28 views
10

大多数语言支持双向过程通信。例如,在Python,我可以(拖泥带水)做:R中的读写管道()通信

>>> 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 < ...运行脚本,奇怪的行为也会在实际的控制台stdin/stdout中出现。

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

回答

4

很久以前,我还在Octave中使用双向管道,所以,这是很好的。但仔细阅读help(pipe)并不表明这是支持。您可以阅读书写,但看起来不是两种。

但也许你可以作弊。打开一个管道写入一个应用程序,您可以调用一个stdout重定向到一个文件...然后继续阅读该文件。尽管如此,由于非刷新缓冲区可能会造成混乱。

+0

这是一个与基地的平台兼容性问题?我应该在那里提交一个错误/问题? 此外,文件选项在技术上是一个解决方案,但实际上这是为了管道大量的SQL结果以避免错误的ODBC驱动程序,因此写入磁盘并重新读入会很慢。 – mjbommar 2011-03-18 18:19:12

+0

我在Linux上试过,如果R支持它的话,它会有它。没有必要提交错误报告,除非您可以编写代码或支付某人的费用--R Core的手已满。最后,我个人倾向于通过......编写直接的数据库访问块来避免错误的ODBC驱动程序。在那里,通过一些GSoC指导,为彭博,Lim,OneTick以及PostgreSQL等后端做好了准备。你的后端是什么? – 2011-03-18 18:29:31

+0

@mjbommar,我还没有找到一种方法来做你所描述的,我花了几个小时尝试。但是,如果您只是试图在不使用ODBC驱动程序的情况下将SQL数据库结果转换为R,则可能不需要双向交互。尝试使用system()连接它并将查询作为输入提供。我这样做是为了访问我所有的数据库(这需要RMySQL无法做到的SSH隧道)。 – Noah 2011-03-18 19:25:48

1

它可能像这样从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 
+0

我投了这个票,因为它可能适用于某些人,但是这个选项会为我的应用程序调用太多开销。 – mjbommar 2011-03-20 15:23:49

+0

@mbommar,你指的是什么开销?如果速度慢,那么''.jython < - rJython()'语句(就像加载JVM一样)只需要在会话开始时执行一次,所以它只影响启动时间。如果启动时间很重要,那么我同意这会是一个问题。 – 2011-03-20 16:16:32

11

一种方式做到这一点的类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] "" 

不幸的是,Windows不支持fifo