我正在尝试将STDOUT从Python / Erlport用管道传输回Elixir。我的:python
调用工作正常,我只想将Python中的STDOUT内容发送回Elixir进行日志记录,但是我无法全力以赴地实现这一目标。即使使用Python 2.7,我也知道它是possible。
我在:python
模块周围有一个Genserver包装器,这样我的呼叫就这样工作:
pid = Python.start()
Python.call(pid, :bridge, :register_handler, [self()])
Python.call看起来像这样:
def call(pid, module, function, args \\ []) do
:python.call(pid, module, function, args)
end
除非我明确返回某些内容(显然暂停了该功能),否则:bridge
中的任何内容(即bridge.py
)都将丢失给STDOUT。如何捕获STDOUT?
我的想法是调用类似Python.call(pid, :builtins, :print, [self()])
之类的东西,但这会导致很多错误,我真的不知道这是否是正确的方向。
我实际上想将其传送到Phoenix频道,但这是最简单的部分(我希望如此)。有什么建议吗?谢谢。
答案 0 :(得分:1)
我的想法是调用类似
Python.call(pid, :builtins, :print, [self()])
之类的东西,但这会导致很多错误,我真的 根本不知道这是正确的方向。
self()
不在输出中,而self()
是print
的参数,即python将输出什么。
我认为erlport
只能处理MFA调用(模块,函数,参数),并且由于print
不是python 2.7
中的函数,因此我认为您需要包装一个函数在print
周围,例如:
myprint.py:
def print_this(str):
print str
我只想将Python中的STDOUT内容发送回Elixir,以便 日志记录,但我无法解决该问题。我知道 即使我使用的是Python 2.7,也是有可能的
erlport文档说:
作为一个方便的功能,ErlPort还支持Python的重定向 STDOUT到Erlang ...
这似乎是默认设置,因此您无需执行任何操作即可将python stdout重定向到elixir stdout。然后问题变成:“如何将elixir stdout登录到文件?”
我可以将长生不老药stdout
登录到这样的文件:
friends.ex:
defmodule Friends do
use Export.Python
def go do
#Get path to logfile:
priv_path = :code.priv_dir(:friends)
logfile_path = Path.join([priv_path, "log", "mylog.log"])
#Redirect stdout:
{:ok, io_pid} = File.open(logfile_path, [:append])
Process.group_leader(self(), io_pid)
#Send output to stdout:
IO.puts "Am I in the log file??!"
python_path = Path.expand("lib/python")
{:ok, py} = Python.start(
python: "python2.7",
python_path: python_path
)
Python.call(py, "myprint", "print_this", ["hello world!"])
Python.call(py, "myprint", "print_this", ["goodbye..."])
Python.stop(py)
end
end
这是我的目录结构:
friends
/lib
/friends
/python
myprint.py
friends.ex
/priv
/log
mylog.log
在iex中:
~/elixir_programs/friends$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Compiling 1 file (.ex)
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Friends.go
iex(2)>
在日志文件中:
Am I in the log file??!
hello world!
goodbye...
[33m[36m:ok[0m[33m[0m
(我不知道最后一行上的垃圾是什么。编辑:嗯……这是原子:ok
被其他东西包围了。)
如果我注释掉python_path行上方go()
内的所有内容,那么我得到:
iex(1)> Friends.go
hello world!
goodbye...
:ok
在erlang / elixir文件中,通过启动一个进程来处理I / O,向该进程发送请求以写入文件或读取文件。我认为stdout会发送到group_leader
的任何进程,如果进程处理文件的I / O是group_leader,则stdout会发送到该文件。
我不知道在使用group_leader
时,弄乱GenServer
是否会使事情搞砸。 erlang docs中有一个警告:
在具有 监督树,因为OTP承担了他们的组长 流程是其应用程序的主人。
。
答案 1 :(得分:0)
对于其他陷入这种困境的人:由于我在:python
实例周围拥有一台Genserver,因此我只是利用了handle_info
:
def handle_info({:python, message}, session) do
message |> String.split("\n", trim: true)
SomeWeb.Endpoint.broadcast("log", "update", %{body: message})
{:stop, :normal, session}
end