Erlang:端口到 Python 实例没有响应
Erlang: port to Python instance not responding
我正在尝试通过 Erlang 端口与外部 python 进程通信。首先,打开一个端口,然后通过标准输入向外部进程发送一条消息。我期待对进程的标准输出的相应回复。
我的尝试是这样的:
% open a port
Port = open_port( {spawn, "python -u -"},
[exit_status, stderr_to_stdout, {line, 1000000}] ).
% send a command to the port
true = port_command( Port, "print( \"Hello world.\" )\n" ).
% gather response
% PROBLEM: no matter how long I wait flushing will return nothing
flush().
% close port
true = port_close( Port ).
% still nothing
flush().
我意识到 someone else on Whosebug 试图做类似的事情,但提议的解决方案显然对我不起作用。
此外,我看到 a related post on Erlang Central 正在通过 Erlang 端口启动 Python 脚本,但调用的不是 Python shell 本身。
我已经注意到 ErlPort 但我有一个完整的脚本要在 Python 中执行。如果可能的话,我不想将脚本分解为单个 Python 调用。
有趣的是,用 bash 做没问题:
Port = open_port( {spawn, "bash"},
[exit_status, stderr_to_stdout, {line, 1000000}] ).
true = port_command( Port, "echo \"Hello world.\"\n" ).
所以上面的例子在冲洗时给了我一个 "Hello world.":
3> flush().
Shell got {#Port<0.544>,{data,{eol,"Hello world."}}}
ok
正是我想看到的。
- Ubuntu 15.04 64 位
- 二郎 18.1
- Python 2.7.9
编辑:
我最终决定将脚本文件(带有 shebang)写入磁盘并执行脚本文件,而不是将脚本通过管道传输到某些语言(如 Python)的语言解释器。
我怀疑,这个问题与一些解释器缓冲 IO 的方式有关,我无法解决这个问题,因此需要额外的一轮磁盘。
正如您所发现的那样,对于这个问题,ports 并没有按照您的意愿行事,这就是 ErlPort 等替代方案存在的原因。此问题的旧解决方法是使用 netcat
将命令通过管道传输到 python,以便出现正确的 EOF。这是一个示例会话:
1> PortOpts = [exit_status, stderr_to_stdout, {line,1000000}].
[exit_status,stderr_to_stdout,{line,1000000},use_stdio]
2> Port = open_port({spawn, "nc -l 51234 | python"}, PortOpts).
#Port<0.564>
3> {ok, S} = gen_tcp:connect("localhost", 51234, []).
{ok,#Port<0.565>}
4> gen_tcp:send(S, "print 'hello'\nprint 'hello again'\n").
ok
5> gen_tcp:send(S, "print 'hello, one more time'\n").
ok
6> gen_tcp:close(S).
ok
7> flush().
Shell got {#Port<0.564>,{data,{eol,"hello"}}}
Shell got {#Port<0.564>,{data,{eol,"hello again"}}}
Shell got {#Port<0.564>,{data,{eol,"hello, one more time"}}}
Shell got {#Port<0.564>,{exit_status,0}}
ok
此方法在端口 51234 上打开一个端口 运行 netcat
作为侦听器 — 当然,您可以选择任何您想要的端口,只要它尚未被使用 — 其输出通过管道传输到 python
。然后我们通过本地 TCP 环回连接到 netcat
并将 python 命令字符串发送到它,然后它通过它的管道转发到 python。关闭套接字会导致 netcat
退出,这会导致 python 的标准输入出现 EOF,进而导致它执行我们发送给它的命令。刷新 Erlang shell 消息队列显示我们通过 Erlang 端口从 python 获得了预期的结果。
我正在尝试通过 Erlang 端口与外部 python 进程通信。首先,打开一个端口,然后通过标准输入向外部进程发送一条消息。我期待对进程的标准输出的相应回复。
我的尝试是这样的:
% open a port
Port = open_port( {spawn, "python -u -"},
[exit_status, stderr_to_stdout, {line, 1000000}] ).
% send a command to the port
true = port_command( Port, "print( \"Hello world.\" )\n" ).
% gather response
% PROBLEM: no matter how long I wait flushing will return nothing
flush().
% close port
true = port_close( Port ).
% still nothing
flush().
我意识到 someone else on Whosebug 试图做类似的事情,但提议的解决方案显然对我不起作用。
此外,我看到 a related post on Erlang Central 正在通过 Erlang 端口启动 Python 脚本,但调用的不是 Python shell 本身。
我已经注意到 ErlPort 但我有一个完整的脚本要在 Python 中执行。如果可能的话,我不想将脚本分解为单个 Python 调用。
有趣的是,用 bash 做没问题:
Port = open_port( {spawn, "bash"},
[exit_status, stderr_to_stdout, {line, 1000000}] ).
true = port_command( Port, "echo \"Hello world.\"\n" ).
所以上面的例子在冲洗时给了我一个 "Hello world.":
3> flush().
Shell got {#Port<0.544>,{data,{eol,"Hello world."}}}
ok
正是我想看到的。
- Ubuntu 15.04 64 位
- 二郎 18.1
- Python 2.7.9
编辑: 我最终决定将脚本文件(带有 shebang)写入磁盘并执行脚本文件,而不是将脚本通过管道传输到某些语言(如 Python)的语言解释器。
我怀疑,这个问题与一些解释器缓冲 IO 的方式有关,我无法解决这个问题,因此需要额外的一轮磁盘。
正如您所发现的那样,对于这个问题,ports 并没有按照您的意愿行事,这就是 ErlPort 等替代方案存在的原因。此问题的旧解决方法是使用 netcat
将命令通过管道传输到 python,以便出现正确的 EOF。这是一个示例会话:
1> PortOpts = [exit_status, stderr_to_stdout, {line,1000000}].
[exit_status,stderr_to_stdout,{line,1000000},use_stdio]
2> Port = open_port({spawn, "nc -l 51234 | python"}, PortOpts).
#Port<0.564>
3> {ok, S} = gen_tcp:connect("localhost", 51234, []).
{ok,#Port<0.565>}
4> gen_tcp:send(S, "print 'hello'\nprint 'hello again'\n").
ok
5> gen_tcp:send(S, "print 'hello, one more time'\n").
ok
6> gen_tcp:close(S).
ok
7> flush().
Shell got {#Port<0.564>,{data,{eol,"hello"}}}
Shell got {#Port<0.564>,{data,{eol,"hello again"}}}
Shell got {#Port<0.564>,{data,{eol,"hello, one more time"}}}
Shell got {#Port<0.564>,{exit_status,0}}
ok
此方法在端口 51234 上打开一个端口 运行 netcat
作为侦听器 — 当然,您可以选择任何您想要的端口,只要它尚未被使用 — 其输出通过管道传输到 python
。然后我们通过本地 TCP 环回连接到 netcat
并将 python 命令字符串发送到它,然后它通过它的管道转发到 python。关闭套接字会导致 netcat
退出,这会导致 python 的标准输入出现 EOF,进而导致它执行我们发送给它的命令。刷新 Erlang shell 消息队列显示我们通过 Erlang 端口从 python 获得了预期的结果。