【问题标题】:How to send messages with Elixir porcelain to a python script?如何使用 Elixir 瓷器将消息发送到 python 脚本?
【发布时间】:2016-10-14 18:18:34
【问题描述】:

我正在尝试学习如何通过 Elixir 与 porcelain module 进行互操作。

所以我做了这个简单的例子:

我有一个 Elixir 函数,如下所示:

defmodule PythonMessenger do
  alias Porcelain.Process, as: Proc
  alias Porcelain.Result

  def test_messages do
    proc = %Proc{pid: pid} =
      Porcelain.spawn_shell("python ./python_scripts/reply_to_elixir.py",
        in: :receive, out: {:send, self()})

    Proc.send_input(proc, "Greetings from Elixir\n")

    data = receive do
      {^pid, :data, :out, data} -> data
    end

    IO.inspect data

    Proc.send_input(proc, "Elixir: I heard you said \"#{data}\"\n")

    data = receive do
      {^pid, :data, data} -> data
    end

    IO.inspect data

    Proc.send_input(proc, "Please quit\n")

    data = receive do
      {^pid, :data, data} -> data
    end

    IO.inspect data
  end
end

还有一个看起来像这样的python脚本:

import sys

while 1:

    line = sys.stdin.readline()
    if "quit" in line:
        print("Quitting, bye for now")
        sys.exit()
    print(line)

但这不起作用。 python 脚本永远不会退出。 如果只读取一行:

  line = sys.stdin.readline()

效果很好。

那么问题出在哪里,有什么想法吗?

【问题讨论】:

标签: python elixir


【解决方案1】:

您需要通过-u 来禁用sys.stdin.readline() 中的缓冲。以交互方式运行程序时您不会看到这一点,但是当程序在没有 TTY 的情况下生成时您会看到它。由于默认缓冲,Python 进程不会为像 "Greetings from Elixir\n" 这样的短消息打印任何内容,并且由于 receive 表达式,Elixir 代码会永远阻塞,等待 Python 进程打印一些内容。

来自man python

   -u     Force  stdin,  stdout  and stderr to be totally unbuffered.  On systems where it matters, also
          put stdin, stdout and stderr in binary mode.  Note that there is internal buffering in  xread-
          lines(),  readlines()  and file-object iterators ("for line in sys.stdin") which is not influ-
          enced by this option.  To work around this, you will want to use "sys.stdin.readline()" inside
          a "while 1:" loop.

您在第二和第三个receive 模式中也有一些错误。这是对我有用的代码:

defmodule PythonMessenger do
  alias Porcelain.Process, as: Proc
  alias Porcelain.Result

  def test_messages do
    proc = %Proc{pid: pid} =
      Porcelain.spawn_shell("python -u ./a.py",
        in: :receive, out: {:send, self()})

    Proc.send_input(proc, "Greetings from Elixir\n")

    data = receive do
      {^pid, :data, :out, data} -> data
    end

    IO.inspect data

    Proc.send_input(proc, "Elixir: I heard you said \"#{data}\"\n")

    data = receive do
      {^pid, :data, :out, data} -> data
    end

    IO.inspect data

    Proc.send_input(proc, "Please quit\n")

    data = receive do
      {^pid, :data, :out, data} -> data
    end

    IO.inspect data
  end
end

PythonMessenger.test_messages

输出:

"Greetings from Elixir\n\n"
"Elixir: I heard you said \"Greetings from Elixir\n\n\n\n"
"\"\n\n"

【讨论】:

  • 有效,但没有收到最后一条消息:-(
  • 这可能是因为在Proc.send_input(proc, "Elixir: I heard you said \"#{data}\"\n") 中,data 包含一个换行符,并且 Python 脚本将该输入读取为多个行。
猜你喜欢
  • 2015-05-03
  • 1970-01-01
  • 2018-03-27
  • 2016-09-11
  • 2016-04-29
  • 2014-07-16
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多