2013-07-20 5 views
5

In R, possiamo aprire una connessione di tubo usando pipe() e scriverci sopra. Ho osservato la seguente situazione che non capisco. Usiamo un tubo python ad esempio:come ottenere l'output da una connessione pipe prima di chiuderlo in R?

z = pipe('python', open='w+') 

cat('x=1\n', file=z) 
cat('print(x)\n', file=z) 
cat('print(x+2)\n', file=z) 
cat('print(x+2\n', file=z) 
cat(')\n', file=z) 

close(z) 

quello che mi aspettavo era l'uscita dal print() sarebbe immediatamente mostrato nella console R, ma il fatto è l'uscita viene solo dopo la chiusura del raccordo:

> z = pipe('python', open='w+') 
> 
> cat('x=1\n', file=z) 
> cat('print(x)\n', file=z) 
> cat('print(x+2)\n', file=z) 
> cat('print(x+2\n', file=z) 
> cat(')\n', file=z) 
> 
> close(z) 
1 
3 
3 

Quindi la mia domanda è: come posso ottenere l'uscita prima di chiudere la connessione? Si noti che non sembra essere possibile catturare l'output utilizzando capture.output(), sia:

> z = pipe('python', open='w+') 
> 
> cat('x=1\n', file=z) 
> cat('print(x)\n', file=z) 
> cat('print(x+2)\n', file=z) 
> cat('print(x+2\n', file=z) 
> cat(')\n', file=z) 
> 
> x = capture.output(close(z)) 
1 
3 
3 
> x 
character(0) 

Lo sfondo di questa domanda è il knitr engines. Per i linguaggi interpretati come Python, mi piacerebbe poter aprire un "terminale" persistente in modo che possa continuare a scrivere codice in esso e ottenerne l'output. Non sono sicuro che se pipe() sia la strada giusta da percorrere, comunque.

risposta

5

Python nota che l'input non è interattivo e attende fino alla chiusura della connessione per analizzare ed eseguire il codice. È possibile utilizzare l'opzione -i per forzarla a rimanere in modalità interattiva. (ma l'output è un po 'stravolto).

z = pipe('python -i', open='w') 
cat('x=1\n', file=z) 
cat('print(x)\n', file=z) 
cat('print(x+2)\n', file=z) 
cat('print(x+2\n', file=z) 
cat(')\n', file=z) 
Sys.sleep(2) 
# Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
# [GCC 4.7.3] on linux2 
# Type "help", "copyright", "credits" or "license" for more information. 
# >>> >>> 1 
# >>> 3 
# >>> ... 3 
# >>> 
close(z) 

Il tuo problema reale è più complicato: devi leggere e scrivere sulla stessa connessione. Non so come farlo in modo portatile, ma puoi usare una pipe e una named pipe (una "fifo") su piattaforme che li supportano.

stopifnot(capabilities("fifo")) 
system('mkfifo /tmp/Rpython.fifo') 
output <- fifo('/tmp/Rpython.fifo', 'r') 
input <- pipe('python -i > /tmp/Rpython.fifo', 'w') 
python_code <- " 
x=1 
print(x) 
print(x+2) 
print(x+2 
) 
" 
cat(python_code, file = input) 
flush(input) 
Sys.sleep(2) # Wait for the results 
result <- readLines(output) 
result 
# [1] "1" "3" "3"