/ / Comment envoyer des messages avec la porcelaine Elixir à un script python? - python, élixir

Comment envoyer des messages avec la porcelaine Elixir à un script python? - python, élixir

J'essaie d'apprendre à faire l'interopérabilité d'Elixir avec le module de porcelaine.

Alors j'ai fait cet exemple simple:

J'ai une fonction Elixir qui ressemble à ceci:

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 Elixirn")

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 quitn")

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

IO.inspect data
end
end

et un script python qui ressemble à ceci:

import sys

while 1:

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

mais ça ne marche pas. Le script python ne se ferme jamais. Si un lu seulement une ligne comme:

  line = sys.stdin.readline()

cela fonctionne très bien.

Alors quel est le problème, des idées?

Réponses:

3 pour la réponse № 1

Vous devez passer -u désactiver la mise en mémoire tampon sys.stdin.readline(). Vous ne verrez pas cela lors de l'exécution du programmede manière interactive, mais vous le verrez lorsque le programme est créé sans TTY. En raison de la mise en mémoire tampon par défaut, le processus Python n’imprimait rien pour un message court tel que "Greetings from Elixirn"et à cause de la receive expression, le code Elixir bloquait pour toujours, attendant que le processus Python imprime quelque chose.

De 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.

Vous avez également eu des erreurs en 2ème et 3ème receive modèles. Voici le code qui fonctionne pour moi:

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 Elixirn")

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 quitn")

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

IO.inspect data
end
end

PythonMessenger.test_messages

Sortie:

"Greetings from Elixirnn"
"Elixir: I heard you said "Greetings from Elixirnnnn"
""nn"