# Input/output to an external process

**URL:** https://discourse.julialang.org/t/input-output-to-an-external-process/78160
**Category:** New to Julia
**Tags:** question, shell
**Created:** [March 20, 2022, 10:25am UTC](https://discourse.julialang.org/t/input-output-to-an-external-process/78160 "2022-03-20T10:25:28Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![dodoplus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dodoplus/32/30148_2.png) [@dodoplus](https://discourse.julialang.org/u/dodoplus)
#### Post date: [March 20, 2022, 10:25am UTC](https://discourse.julialang.org/t/input-output-to-an-external-process/78160/1 "2022-03-20T10:25:28Z")

</div>

Hi,

I want to both read _and_ write to an external process.  
It seems that if e.g. I just want to read _or_ write to a process, there’s a nice way of doing that (from the docs):

```julia
open(`less`, "w", stdout) do io
     for i = 1:3
         println(io, i)
     end
 end

```

However, if I want to do both, the best I can find is resorting to a hack (from Gaston.jl):

```julia
pin = Pipe()
pout = Pipe()
perr = Pipe()
proc = run(pipeline(`cat`, stdin = pin, stdout = pout, stderr = perr), wait = false)
process_running(proc) || error("not running")
close(pout.in)
close(perr.in)
close(pin.out)

write(pin, "test\n")
@show(readline(pout))

# output:
# readline(pout) = "test"

```

Surely there’s a better way…

Thanks,

DD

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [March 20, 2022, 10:35am UTC](https://discourse.julialang.org/t/input-output-to-an-external-process/78160/2 "2022-03-20T10:35:44Z")

</div>

Have a look at  
[https://github.com/emmt/InterProcessCommunication.jl](https://github.com/emmt/InterProcessCommunication.jl)  
I don’t know whats the state of this package but you will get some hints out of the package to what you can look for. I found it searching for “semaphore” for Julia. Semaphores are as I remember some typical way for inter process communications.

---

<div class="post-metadata">

### Author: ![dodoplus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dodoplus/32/30148_2.png) [@dodoplus](https://discourse.julialang.org/u/dodoplus)
#### Post date: [March 20, 2022, 12:27pm UTC](https://discourse.julialang.org/t/input-output-to-an-external-process/78160/3 "2022-03-20T12:27:32Z")

</div>

Thanks, but this seems like an implementation of various IPC primitives such as semaphores, locks, etc.  
It doesn’t seem to deal with _starting_ a process…

Using the code above, I can hack something that hides the ugly in minutes:

```julia
function wrap(f, cmd::Cmd)
    pin = Pipe()
    pout = Pipe()
    perr = Pipe()
    proc = run(pipeline(cmd, stdin = pin, stdout = pout, stderr = perr), wait = false)
    process_running(proc) || error("not running")
    close(pout.in)
    close(perr.in)
    close(pin.out)
    
    return f(pin, pout, perr)
end

wrap(`cat`) do pin, pout, perr
     println(pin, "test")
     println(readline(pout))
end

# outputs: test

```

I’m surprised there’s nothing similar in the standard library (which will handle all the edge cases my hack above doesn’t).

DD

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 20, 2022, 2:19pm UTC](https://discourse.julialang.org/t/input-output-to-an-external-process/78160/4 "2022-03-20T14:19:49Z")

</div>

> [@dodoplus](#):
>
> I’m surprised there’s nothing similar in the standard library (which will handle all the edge cases my hack above doesn’t).

Probably because that specific use case is a little niche, especially without returning the `Process` object itself (e.g. to chain it via another `pipeline` or introspect exit status…). There’s also a possible ambiguity in regards to whether `f` or `wrap` should close the created `Pipe`s, as some functions may want to write to that `stdin` of the spawned process for some initial setup (which you can’t do if `wrap` already closed them). Additionally, it’s debatable whether `f` or `wrap` should close the pipe inputs/outputs at all, as usually the `do` notation in functions with sideeffects is used to clean up/do ressource management (and thus could close the pipe ends…). Exposing those options as part of `wrap` would not be much less “overhead” than writing the `Pipe`s and `close` calls yourself, for your specific usecase.
