I'm trying to redirect stdin and stdout of a console application, so that I can interact with them via F#. However, depending on the console application the obvious code seems to fail. The following F# code works for dir
but fails (hangs) for python
and fsi
:
open System
open System.Diagnostics
let f = new Process()
f.StartInfo.FileName <- "python"
f.StartInfo.UseShellExecute <- false
f.StartInfo.RedirectStandardError <- true
f.StartInfo.RedirectStandardInput <- true
f.StartInfo.RedirectStandardOutput <- true
f.EnableRaisingEvents <- true
f.StartInfo.CreateNoWindow <- true
f.Start()
let line = f.StandardOutput.ReadLine()
This hangs for python but works for dir.
Does this have do with python and fsi using readline or am I making an obvious mistake? Is there a work around that would allow me to interact with fsi or python REPL from F#?
I'll bet neither python nor fsi are actually generating a line of text to be read. The call to
ReadLine
will block until a full line ending with a carriage return or linefeed is available.Try reading a character at a time (with
Read
instead ofReadLine
) and see what happens.This is the code you are looking for (which I conveniently have written in Chapter 9, Scripting ;) As mentioned earlier, ReadLine blocks until there is a full line which leads to all sorts of hangs. Your best bet is to hook into the OutputDataRecieved event.
Output (which could stand to be prettied up):
It's probably what Michael Petrotta says. If that's the case, even reading a character won't help. What you need to do is to use the asynchronous versions (BeginOutputReadLine) so that your app won't block.