Communication with a command line program


I’m trying to set-up communication with an interactive program.
I’ll use bc for my example.

I quickly found that this works:

julia> (p, process)=open(`bc`, "w", STDOUT)
(Pipe(open => closed, 0 bytes waiting),Process(`bc`, ProcessRunning))

julia> write(p, "2*3\n")

However, what I can’t figure out is what to substitute for STDOUT.

open(cmds::Base.AbstractCmd, mode::AbstractString, other::Union{Base.FileRedirect,IO,RawFD})

I thought the most obvious thing was to use an IOBuffer so that the process would simple write into the buffer and then of course I could read from it, but that is not type compatible.

julia> s=IOBuffer(100)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=100, ptr=1, mark=-1)

julia> (p, process)=open(`bc`, "w", s)
ERROR: MethodError: no method matching uvtype(::Base.AbstractIOBuffer{Array{UInt8,1}})
Closest candidates are:
  uvtype(::RawFD) at process.jl:158
  uvtype(::Base.DevNullStream) at process.jl:151
  uvtype(::Base.Filesystem.File) at filesystem.jl:70

ok, no problem, I just need to turn by IOBuffer into a File. And that’s where i get stuck.

Any hints ?

Thank you!

If your objective is to write to a file, just use a plain old file:

julia> f = open("/tmp/foo","w")
IOStream(<file /tmp/foo>)

julia> (p, process)=open(`bc`, "w", f)
(Pipe(RawFD(22) open => RawFD(-1) closed, 0 bytes waiting), Process(`bc`, ProcessRunning))

julia> write(p, "2*3\n")

julia> close(f)

phasebang:~$ cat /tmp/foo

No, the objective is to communicate back and forth with the program. So I don’t want to just dump the output to a file- although your example is useful- but to keep the link open.

So what I want to do is open a string buffer or iobuffer as an iostream so i can continually read back from it.
so in python this just uses the Popen function with stdin and stdout assigned to Subprocess.PIPE. I then get file objects I can read from and write to.

edit: i guess i could open a file as the output, leave it open, and then open another, read-only stream to that file to get output from it… That seems very kludgey.

I knew it would be easy, and that Julia would have something built in…

julia> (sout, sin, p) = readandwrite(`bc`)
(Pipe(closed => open, 0 bytes waiting),Pipe(open => open, 0 bytes waiting),Process(`bc`, ProcessRunning))

julia> write(sin, "2*3\n")

julia> readline(sout)

julia> write(sin, "2*10\n")

julia> readline(sout)