Example of usage of an Erlang port
(April 2011)
This page gives an example, designed as follows:
The Erlang program (test_port.erl), that is in charge of the computing, sends data via a port to the Python program (test_port.py), that is in charge of the display.
The result is like this:
The dots are some moving bodies, and each dot is linked to the three nearest dots.
In order to run this example, you need at least:
- Erlang R13B03 (erts-5.7.4)
- Python 2.6
- test_port.erl
- test_port.py
Then run:
erlc +debug_info test_port.erl
erl -run test_port start
If you want to test only the Python part, you may download sample_data.log and run this:
cat sample_data.log | python test_port.py
# or if you want profiling:
cat sample_data.log | python -m cProfile test_port.py
# or if you want to debug
python -m pdb test_port.py -i sample_data.log
The Erlang port is technically achieved as follows:
- The Erlang machine creates the Python process
- A pipe is created between the Erlang machine and the Python process
- On the Python side the pipe is connected to stdin and stdout
Data sent via the port to the Python displayer looks like this:
...
<0.39.0>: x=300.48, y=489.93, pid1=<0.36.0>, pid2=<0.37.0>, pid3=<0.35.0>
<0.45.0>: x=372.63, y=154.37, pid1=<0.38.0>, pid2=<0.46.0>, pid3=<0.34.0>
<0.49.0>: x=674.50, y=127.33, pid1=<0.53.0>, pid2=<0.56.0>, pid3=<0.41.0>
<0.61.0>: x=910.48, y=264.60, pid1=<0.62.0>, pid2=<0.57.0>, pid3=<0.53.0>
<0.54.0>: x=545.77, y=359.24, pid1=<0.47.0>, pid2=<0.55.0>, pid3=<0.50.0>
<0.40.0>: x=152.31, y=348.52, pid1=<0.35.0>, pid2=<0.36.0>, pid3=<0.37.0>
<0.52.0>: x=496.86, y=579.55, pid1=<0.48.0>, pid2=<0.44.0>, pid3=<0.55.0>
...
The present example runs 32 moving bodies.
The bodies move around randomly, except that we try to keep them close to their original position.
Download test_port.erl
Excerpt of test_port.erl
Port = open_port({spawn, "python test_port.py"}, [stream]),
...
Data = io_lib:format("~p: x=~.2f, y=~.2f, pid1=~p, pid2=~p, pid3=~p\n", [ self(), X, Y, Pid1, Pid2, Pid3 ]),
port_command(Port, Data),
The present example uses Tkinter for the display.
Download test_port.py
Excerpt of test_port.py
line = sys.stdin.readline()
...
matchingObject = re.match("(.*): x=([0-9\.]*), y=([0-9\.]*), pid1=(.*), pid2=(.*), pid3=(.*)", line)
if matchingObject is not None:
pid = matchingObject.group(1)
x = matchingObject.group(2)
y = matchingObject.group(3)
pid1 = matchingObject.group(4)
pid2 = matchingObject.group(5)
pid3 = matchingObject.group(6)