最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Phoenix liveview with python business process - but the communication fails - Stack Overflow

programmeradmin2浏览0评论

I have a phoenix app, where I’m using liveview to get user inputs through a UI. These inputs get packaged into JSON and sent to a python business process (script), which in turn returns the results in JSON to the liveview, where they get displayed.

I am sending my JSON successfully to the python, running it and getting the results, however I don’t get the result when running it from liveview (when I run my python mynaully in the terminal, the results json is returned fine). It should be a straightforward thing, im sure im missing a really easy point. Can anyone help? FYI, my python business process takes 0.03 seconds tu run when running manually from start to finish

Python I'm calling:

def main():
    try:
        raw_input = sys.stdin.read().strip()
        input_data = json.loads(raw_input)
        results = optimizer_function(input_data) # optimizer_function is my business process
        output = json.dumps(results)
        sys.stdout.write(output + "\n")
        sys.stdout.flush()
    except Exception as e:
        sys.stdout.write(json.dumps({"error": str(e)}) + "\n")
        sys.stdout.flush()

if __name__ == "__main__":
    main()

My Phoenix Optimizer business process code snippets:

defmodule Commrefiner.Optimizer do
  def run_optimizer(params) do
    json_input = Jason.encode!(params)
    script_path = Application.fetch_env!(:commrefiner, :optimizer_script_path)

    port = Port.open({:spawn_executable, "path/to/virtual/environment/python3"}, [
      {:args, [script_path]},
      :binary,
      :exit_status,
      :use_stdio,
      :stderr_to_stdout
    ])

    Portmand(port, json_input <> "\n")
    response = collect_output(port, "")
    Port.close(port)

    case Jason.decode(response) do
      {:ok, result} -> result
      {:error, _} -> %{"error" => "Invalid JSON response from optimizer"}
    end
  end

  defp collect_output(port, acc) do
    case Port.info(port, :os_pid) do
      {:os_pid, _pid} ->
        receive do
          {^port, {:data, output}} -> collect_output(port, acc <> output)
          {^port, {:exit_status, status}} -> acc
        after
          15_000 ->  # ✅ Allow enough time for Python output
            acc
        end
      nil ->
        acc
    end
  end
end

My Phoenix Live_view code snippets:

  def handle_event("run_optimizer", _params, socket) do
    params = %{params: socket.assigns.user_inputs}
    headers = [{"Content-Type", "application/json"}] # Define and ensure correct headers

    # encode JSON before sending
    response = HTTPoison.post("http://localhost:4000/api/optimizer", Jason.encode!(params), headers)

    case response do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        case Jason.decode(body) do
          {:ok, results} -> {:noreply, assign(socket, results: results)}
          {:error, _} -> {:noreply, assign(socket, results: %{"error" => "Invalid JSON response"})}
        end

      {:ok, %HTTPoison.Response{status_code: code, body: body}} ->  # ✅ Handle non-200 responses
        IO.puts("❌ API returned status #{code}")
        IO.inspect(body, label: "Non-200 Response")
        {:noreply, assign(socket, results: %{"error" => "API error: #{code}"})}

      {:error, %HTTPoison.Error{reason: reason}} ->  # ✅ Handle request errors
        IO.puts("❌ Optimizer API request failed")
        IO.inspect(reason, label: "Optimizer API Error")
        {:noreply, assign(socket, results: %{"error" => "Failed to call optimizer"})}
    end
  end

My logs indicate:

Timeout in the Phoenix API request:

  • Optimizer API Error: :timeout
  • Python process timed out. Partial Data: "" Python script does not send any output before the timeout:
  • Full Raw Response from Python: ""
  • Raw Python Output: "" What’s Happening?
  • Phoenix opens the port to run the Python script.
  • It sends the JSON input.
  • Python does not send output before the timeout.
  • The API request times out before Python can return data.
  • Phoenix closes the connection, causing Python to fail with BrokenPipeError.
发布评论

评论列表(0)

  1. 暂无评论