Recursive Port receive works in iex but hangs in Livebook

Working with iex I was successful in getting result back from recursive receive of Python script. As below,

Interactive Elixir (1.14.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule Flush do
...(1)> def do_flush() do
...(1)>     receive do
...(1)>     msg ->
...(1)>       IO.inspect(msg)
...(1)>       do_flush()
...(1)>   after
...(1)>     0 -> :ok
...(1)>   end
...(1)> end
...(1)> end
{:module, Flush,
 <<70, 79, 82, 49, 0, 0, 5, 216, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 193,
   0, 0, 0, 20, 12, 69, 108, 105, 120, 105, 114, 46, 70, 108, 117, 115, 104, 8,
   95, 95, 105, 110, 102, 111, 95, 95, 10, ...>>, {:do_flush, 0}}
iex(2)> temp = 16
16
iex(3)> press = 1500
1500
iex(4)> port = Port.open({:spawn, "python3 /Users/gani/Desktop/test.py #{temp} #{press}"}, [:binary])
#Port<0.5>
iex(5)> Flush.do_flush()
{#Port<0.5>, {:data, "1945.335612109853\n"}}
:ok

But the same doesn’t work in Livebook. When I do

Flush.do_flush()

It hangs till I click on “stop”. Why this weird behavior?

However, this works:

receive do
  {^port, {:data, result}} ->
    IO.puts("Elixir got: #{inspect(result)}")
end

I would like help on:

  1. why doesn’t the function Flush.do_flush() work in Livebook but works in iex,
  2. but more importantly, (because the 2nd version works ok), how do I capture value from :data into a variable.

I’m (still) a newbie, so would appreciate help.

Thanks,
Gani -

1 Like

ok, I figured it out. In Livebook, I implemented as:

temp = 15
press = 1200.0
port = Port.open({:spawn, "python3 test.py #{temp} #{press}"}, [:binary])
output = receive do
  {^port, {:data, result}} -> result
  |> String.trim("\n") 
  |> String.to_float()
end  #=> 1860.7140685878487

erlport is an alternative to port when You want to communicate with Python, or Ruby …

… for an easier communication management.

I’d be hesitant to adopt a library that hasn’t been updated in 7 years and has all indications of being a dead project…

Yes, I want to stay in Elixir and erlport appears to be Erlang. I’m sure it can be used, but Port works fine.

gani-

I have the same problem in Livebook.

Did you solve this problem?

I found that the Port is gone after few time.

for example

port = Port.open({:spawn, "python -c 'print(1)'"}, [:binary])
Port.close(port)

---

true
port = Port.open({:spawn, "python -c 'print(1)'"}, [:binary])

Process.sleep(1000)

Port.close(port)

---

** (ArgumentError) argument error
    :erlang.port_close(#Port<0.25>)
    #cell:obc2dqwid3usltnj3bxw6qkfafzkpabt:7: (file)

Hi, I’ve just released Doumi.Port - A helper library that facilitates the usage of Python in Elixir.

This library will make it much easier to use Python in Elixir.
And it works in Livebook well!

Thanks!