[英]Elixir/Erlang: Communication with external process
假設我有一個簡單的python腳本,它使用subprocess
模塊執行elixir / erlang腳本。
假設python腳本的OS PID是P1
並且運行的生成的elixir / erlang腳本的OS是P2
。
我想知道P1
和P2
之間的通信是否可行。 更具體地說, P1
向P2
的stdin
寫入一些內容, P2
從P1
讀取接收到的輸入,並將一些相應的輸出寫入其自己的stdout
, P1
從P2
的stdout
讀取,並再次向P2
的stdin
寫入內容,依此類推。
我知道另一種方式是可能的,即從elixir / erlang內部生成外部進程,然后與進程通信。 任何幫助表示感謝,謝謝。
是的,這種跨語言的IPC是完全可能的。 絕大多數文檔和博客文章等(以及到目前為止在StackOverflow上的響應!)假設與您似乎要求的相反 - 也就是說,他們假設Erlang / Elixir正在生成Python子流程,而不是Python產生Erlang / Elixir子進程。 如果這沒關系(即你的Erlang或Elixir應用程序可以啟動Python過程),那就太好了! Badu的答案將幫助您做到這一點,您也可以在Elixir的Port
模塊的文檔中獲得額外的參考。
但這似乎不是你尋求的答案,而且那不那么有趣。 世界需要更多關於如何反過來的文檔,所以讓我們深入探討運行Erlang作為Python腳本子過程的奇妙世界!
首先,我們的Python腳本( eip.py
):
#!/usr/bin/env python
from subprocess import Popen, PIPE
erl = Popen(['escript', 'eip.escript'],
stdin=PIPE, stdout=PIPE, stderr=PIPE)
ping = input('Ping: ')
outs, errs = erl.communicate(input=ping.encode('utf-8'),
timeout=15)
print(outs.decode('utf-8'))
在Erlang方面(正如你在Python代碼中可能已經注意到的),一個非常簡單的方法是使用escript
程序,它允許我們編寫或多或少的自包含Erlang腳本,像這樣這里是eip.escript
:
#!/usr/bin/env escript
main(_Args) ->
Ping = io:get_line(""),
io:format("Pong: ~ts", [Ping]).
現在,當你運行python3 eip.py
並在Ping:
提示符下輸入asdf
時,你應該回到Pong: asdf
。
使用Elixir做同樣的事情只是稍微復雜一些:我們需要創建一個帶有一些額外配置的Mix項目,這樣就告訴Mix將一個escript文件放在一起。 那么讓我們從項目開始:
$ mix new eip
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/eip.ex
* creating test
* creating test/test_helper.exs
* creating test/eip_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd eip
mix test
Run "mix help" for more commands.
(對於這個簡單的例子來說甚至使用Mix可能有點過頭了,但我假設你最終想要做比這個例子更高級的事情)
接下來,你要添加一個escript
選項,您mix.exs
,就像這樣:
defmodule Eip.MixProject do
use Mix.Project
def project, do: [
app: :eip,
version: "0.1.0",
elixir: "~> 1.9",
start_permanent: Mix.env() == :prod,
deps: deps(),
escript: escript()
]
def application, do: [extra_applications: [:logger]]
defp deps, do: []
defp escript, do: [main_module: Eip]
end
最后,你的lib/eip.ex
模塊:
defmodule Eip do
def main(_argv) do
ping = IO.gets("")
IO.puts("Pong: #{ping}")
end
end
現在我們只需要構建它:
$ mix escript.build
Compiling 1 file (.ex)
Generated eip app
Generated escript eip with MIX_ENV=dev
eip.py
需要稍加調整才能指向這個新的Elixirified ping / pong IPC thingamabob:
#!/usr/bin/env python
from subprocess import Popen, PIPE, TimeoutExpired
erl = Popen(['escript', 'eip/eip'],
stdin=PIPE, stdout=PIPE, stderr=PIPE)
ping = input('Ping: ')
outs, errs = erl.communicate(input=ping.encode('utf-8'))
print(outs.decode('utf-8'))
不幸的是,這並不完全有效:
$ python3 eip.py
Ping: asdf
Pong: eof
即使使用Erlang版本的更直接端口( IO.gets("")
替換為:io.get_line("")
和IO.puts("Pong: #{ping}")
,也會發生相同的結果:io.fwrite("Pong: ~ts", [ping])
,這意味着特定於Elixir的STDIN處理通常會導致它過早地認為它已達到文件末尾。但是,至少有一個方向可行!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.