Tuesday, March 24, 2009

erlang和python交互

最近开发 Erlang ,对其字符串处理能力无言至极,于是决定把它和python联合起来,打造一个强力的分布式系统,等将来需要系统级开发时,我再把 C++/C组合进来.

首先参考了 Erlang 官方文档和 http://blog.developers.api.sina.com.cn/?tag=erlang 以及 http://kazmier.net/computer/port-howto/ .

研读了将近24个小时, 才终于完全把问题解决. 开始 python 一直是broken pipe.后来才知道是管道中断导致的问题.

接着我排除了python的问题, 在erlang上面发现了Timeout, 感谢litaocheng的提醒,翻看了文档,把gen_server:call 的超时控制为infinity, 这样完全排除了超时的错误.

后来发现执行combin()之后,系统一直在等待. 我重新参考了下前面的2个成功案例,数据流的结尾应该
加上"\n"(windows为"\t\n"),并且erlang需要转换二进制,于是就是

String = list_to_binary("combine|"++_String++"\n"),

python端就成功收到了Stream.
这里combine只是我自己定的一个通信协议 合成请求|String1,String2 => string1+string2.








%%%-------------------------------------------------------------------  

%%% File    : gen_server_template.full  

%%% Designer  : free.Won <freefis@Gmail.com>  

%%% Description :  

%%%     Communication between Python and Erlang via Stdio.  

%%% Archieved :  Mar 24 2009 by  free.Wang <freefis@Gmail.com>  

%%%-------------------------------------------------------------------  

-module(comm).  

-behaviour(gen_server).  

%% API  

-export([start/0,combine/1]).  

%% gen_server callbacks  

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,  

     terminate/2, code_change/3]).  

-record(state, {port}).

  

start() ->  

    gen_server:start_link({global, ?MODULE}, ?MODULE, [], []).

init([]) ->  

    process_flag(trap_exit, true),

    Port = open_port({spawn, "python -u /home/freefis/Desktop/comm.py"},[stream,{line, 1024}]),

    {ok, #state{port = Port}}.

handle_call({combine,String}, _From, #state{port = Port} = State) ->  

    port_command(Port,String),

    receive

        {Port,{data,{_Flag,Data}}} -> 

            io:format("receiving:~p~n",[Data]),

            sleep(2000),

            {reply, Data, Port}

    end.

handle_cast(_Msg, State) ->  

    {noreply, State}.  

handle_info(Info, State) ->

    {noreply,State}.

%    {stop, {port_terminated, Reason}, Port}.

terminate(_Reason, Port) ->  

    ok.

code_change(_OldVsn, State, _Extra) ->  

    {ok, State}.  

  

%%--------------------------------------------------------------------  

%%% Internal functions  

%%--------------------------------------------------------------------

sleep(T) ->

    receive

        after T ->

            true

    end.

combine(_String) ->

    String = list_to_binary("combine|"++_String++"\n"),

    gen_server:call({global,?MODULE},{combine,String},infinity).








#!/usr/bin/env python

# -*- coding:utf-8 -*-

#-------------------------------------------

# Designer  : Free.Wang

# E-mail    : freefis@Gmail.com

# Licence   : License on GPL Licence

# Archieved : Dec 27 2008

#-------------------------------------------







import sys



def handle(_string):

    if _string.startswith("combine|"):

        string = "".join( _string[8:].split(","))

    return string







"""waiting for input """

while 1:

    # Recv. Binary Stream as Standard IN

    _stream = sys.stdin.readline()

    if not _stream: break

    # Scheme, Turn into  Formal String

    inString  = _stream.strip("\r\n")

    # handle String

    outString = handle(inString)

    # send to port as Standart OUT

    sys.stdout.write("%s\n" % (outString,))

    sys.exit(0)


No comments:

Followers