Dumping Python Pickle Files from Java

Pickle is a powerful serializing and deserializing mechanism supported by Python. With Jython jar file, we can load and dump Python pickle files from Java. Loading pickle file from Java has already been covered in a previous post. This post will discuss how to dump data to a pickle file in Java so a python script can deserialize it.

0. Download Jython jar file and the sources.jar file from Jython website.  Suppose we are using Eclipse IDE, add the downloaded Jython jar file as a library. We can also set the sources.jar as the attached source for the jar library for easier debugging.

1. Dump the data to a pickle file ids.pkl. The following Java from demonstrates how to put the data in a Java HashSet to a PyList and dump it.

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.OutputStream;

import java.util.HashSet;

 

import org.python.core.PyFile;

import org.python.core.PyList;

import org.python.core.PyString;

import org.python.modules.cPickle;

 

 

 

public class DumpPickle {

    public static void main(String[] args) {

        HashSet<String> appIds = new HashSet<String>();

        appIds.add("1234321432");

        appIds.add("1234321433");

        appIds.add("xsydfsflkfds");

        DumpPickle afpd = new DumpPickle();

        afpd.dumpHashsetToPickle(appIds);

    }

    

    public void dumpHashsetToPickle(HashSet<String> pIds) {

        File f = new File("ids.pkl");

        OutputStream fs = null;

        try {

            fs = new FileOutputStream(f);

        } catch (FileNotFoundException e) {

            e.printStackTrace();

            return;

        }

        PyFile pyF = new PyFile(fs);

        PyList pyIdList = new PyList();

        for (String id : pIds) {

            PyString pyStr = new PyString(id);

            pyIdList.add(pyStr);

        }

        cPickle.dump(pyIdList, pyF);

        pyF.flush();

        pyF.close();

    }

 

}

Note that we will need to convert the Java data structure to Jython data structure before the dump operation.

2. Load the data from the pickle file ids.pkl. Below is a simple Python script that deserializes the data from ids.pkl to a list.

#!/usr/bin/python

import pickle

ids = []

ids = pickle.load( open( "ids.pkl", "r" ) )

for i in range(len(ids)):

    print ids[i]

3. Sample Execution

We can run the Java program first to produce the ids.pkl file, and then run the python script, which should print out the following.

1234321433
xsydfsflkfds
1234321432

As expected, we can get the list from the ids.pkl file.

Side note: the Jython jar file used for testing is jython-2.5.3.jar.

References:

Jython website: http://www.jython.org/

Loading Python Pickle Files from Java

Recently I wrote some program in Python, which dumps data into a pickle file. The file data is loaded into memory by another Python program for further processing. This works pretty well until I need to write a Java program which also loads the data saved in the pickle file.

I searched around but cannot find many resources about loading pickle files from Java. A few forum discussions mentioned calling Python script from Java using Jython interpreter. I digged deeper into the Jython implementation and found that we can actually load pickle files in Java with the help of Jython jar library.

Below we describe the steps of how to load pickle files from Java code.

0. Download Jython jar file and the sources.jar file from Jython website.  Suppose we are using Eclipse IDE, add the downloaded Jython jar file as a library. We can also set the sources.jar as the attached source for the jar library for easier debugging.

1. Create a Python pickle (or cpickle) File. Below is a simple Python script that dump a dictionary of lists to a pickle file.

#!/usr/bin/python

#import cPickle as pickle    #use either cpickle or pickle

import pickle

idToCountries = {}

testa = []

testa.append("us")

testa.append("en")

idToCountries["12345"] = testa

testb=[]

testb.append("cn")

testb.append("th")

idToCountries["12346"] = testb

outf=open("test.pkl", "wb")

pickle.dump(idToCountries, outf)

Save the file as test.py, and execute the commands below to create the test.pkl pickle file.

chmod +x test.py

./test.py

2. Load the data from the pickle file test.pkl, and put the data into a HashMap of ArrayLists. This is demonstrated in the Java file below.

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.concurrent.ConcurrentMap;

import java.io.FileInputStream;

import java.io.InputStream;

 

import org.python.core.PyDictionary;

import org.python.core.PyFile;

import org.python.core.PyList;

import org.python.core.PyObject;

import org.python.core.PyString;

import org.python.modules.cPickle;

 

public class PickleLoader {

    

    public static void main(String[] args) {

        PickleLoader loader = new PickleLoader();

        HashMap<String, ArrayList<String>> loadCnt1 =  loader.getIdToCountriesStr();

        System.out.println(loadCnt1.toString());

        HashMap<String, ArrayList<String>> loadCnt2 =loader.getIdToCountriesFileStream();

        System.out.println(loadCnt2.toString());

    }

    

    public HashMap<String, ArrayList<String>> getIdToCountriesStr() {

        HashMap<String, ArrayList<String>> idToCountries = new HashMap<String, ArrayList<String>>();

        File f = new File("test.pkl");

        System.out.println(f.length());

        BufferedReader bufR;

        StringBuilder strBuilder = new StringBuilder();

        try {

            bufR = new BufferedReader(new FileReader(f));

            String aLine;

            while (null != (aLine = bufR.readLine())) {

                strBuilder.append(aLine).append("n");

            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

        PyString pyStr = new PyString(strBuilder.toString());

        PyDictionary idToCountriesObj =  (PyDictionary) cPickle.loads(pyStr);

        ConcurrentMap<PyObject, PyObject> aMap = idToCountriesObj.getMap();

        for (Map.Entry<PyObject, PyObject> entry : aMap.entrySet()) {

            String appId = entry.getKey().toString();

            PyList countryIdList = (PyList) entry.getValue();

            List<String> countryList = (List<String>) countryIdList.subList(0, countryIdList.size());

            ArrayList<String> countryArrList = new ArrayList<String>(countryList);

            idToCountries.put(appId, countryArrList);

        }

//        System.out.println(idToCountries.toString());

        return idToCountries;

    }

    

    public HashMap<String, ArrayList<String>> getIdToCountriesFileStream() {

        HashMap<String, ArrayList<String>> idToCountries = new HashMap<String, ArrayList<String>>();

        File f = new File("test.pkl");

        InputStream fs = null;

        try {

            fs = new FileInputStream(f);

        } catch (FileNotFoundException e) {

            e.printStackTrace();

            return null;

        }

        PyFile pyStr = new PyFile(fs);

        PyDictionary idToCountriesObj =  (PyDictionary) cPickle.load(pyStr);

        ConcurrentMap<PyObject, PyObject> aMap = idToCountriesObj.getMap();

        for (Map.Entry<PyObject, PyObject> entry : aMap.entrySet()) {

            String appId = entry.getKey().toString();

            PyList countryIdList = (PyList) entry.getValue();

            List<String> countryList = (List<String>) countryIdList.subList(0, countryIdList.size());

            ArrayList<String> countryArrList = new ArrayList<String>(countryList);

            idToCountries.put(appId, countryArrList);

        }

//        System.out.println(idToCountries.toString());

        return idToCountries;

    }

}

The getIdToCountriesStr method reads all the data from the pickle file and pass it as a string to the Jython cPickle.loads method. The getIdToCountriesFileStream open the file as FileInputStream and pass it to Jython cPickle.load method. This is preferred method for large pickle files.

In addition to loading the file, we also need to perform data type conversion to convert the PyList to List and then ArrayList, and PyDictionary to HashMap.

3. Sample Execution

The execution of the Java program will give us the following output.

{12346=[cn, th], 12345=[us, en]}
{12346=[cn, th], 12345=[us, en]}

As expected, both methods can load data from pickle file and save them into a Java HashMap.

Side note: the Jython jar file used for testing is jython-2.5.3.jar.

References:

Jython website: http://www.jython.org/

Access Cassandra from Python with pycassa

pycassa is a Python client for Apache Cassandra databases. The source code of pycassa can be found at https://github.com/pycassa/pycassa.

0. Install pycassa

sudo easy_install pycassa

or

sudo pip install pycassa

1. Read and Write

Reading and writing with pycassa is easy. We connect to the database, get the column family, and then read from and write to the column family. Below is a simple script demonstrates the basic read and write in pycassa.

#!/usr/bin/python

import os

import datetime

import pycassa


dbHost="localhost"

dbPort="9160"

keyspace="test"

cf="testcf"

rowKey="bbb"


DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"


connectStr=dbHost + ":" + dbPort

print connectStr


pool = pycassa.pool.ConnectionPool(keyspace, [connectStr], timeout=10)

colFam = pycassa.ColumnFamily(pool, cf)

#try to get the row first

try:

    res = colFam.get(rowKey);

except Exception,e:

    res = ""

print res

#insert a column for the row

colFam.insert(rowKey, {'testTime':datetime.datetime.now().strftime(DATETIME_FORMAT)})

#get the row again

res = colFam.get(rowKey);

print res

The output of the script is as below. The second line indicates the row value before write and the third line shows the value after write. Note that the keyspace and column family should have been created before running the script.

2. More about read and Batch Write

We can read a specific column or a slice of columns. We can also perform batch writes. This is shown in the script below.

#!/usr/bin/python

import os

import datetime

import pycassa


dbHost="localhost"

dbPort="9160"

keyspace="test"

cf="testcf"

rowKey="bbb"


DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"


connectStr=dbHost + ":" + dbPort

print connectStr


pool = pycassa.pool.ConnectionPool(keyspace, [connectStr])

colFam = pycassa.ColumnFamily(pool, cf);

try:

    ret = colFam.get(rowKey, ["testTime"]);

except Exception,e:

    ret = ""

print "get with column name: " + str(ret)


try:

    ret = colFam.get(rowKey, column_start="aa", column_finish="zz");

except Exception,e:

    ret = ""

print "get with column slice: " + str(ret)


bat = colFam.batch(queue_size=50)

bat.insert(rowKey, {'testTime':datetime.datetime.now().strftime(DATETIME_FORMAT)})

bat.insert(rowKey, {'testTime2':datetime.datetime.now().strftime(DATETIME_FORMAT)})

bat.send()


print "after insert: " + str(colFam.get(rowKey));

The output of the script is shown as below. Note that the batch write is not necessary in our example since we are writing to the same row. Batch write is usually used to update multiple rows.

3. Unicode

Pycassa will automatically detect the character encoding based on default_validation_class of the column family. We can set this value to pycassa.types.UTF8Type() to instruct pycassa to use UTF-8 encoding. One use case is the the column family’s validation class is set to BytesType, and we want to write UTF-8 characters to the column family. Below is a script shows usage of UTF-8 at pycassa.

#!/usr/bin/python

import os

import datetime

import pycassa


dbHost="localhost"

dbPort="9160"

keyspace="test"

cf="testcf"

rowKey="bbb"


DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"


connectStr=dbHost + ":" + dbPort

print connectStr


pool = pycassa.pool.ConnectionPool(keyspace, [connectStr])

colFam = pycassa.ColumnFamily(pool, cf);

colFam.default_validation_class = pycassa.types.UTF8Type()

try:

    colFam.remove(rowKey, ["money"])

    ret = colFam.get(rowKey, ["money"]);

except Exception,e:

    ret = ""

print "get with column name: " + str(ret)


try:

    ret = colFam.get(rowKey, column_start="aa", column_finish="zz");

except Exception,e:

    ret = ""

print "get with column slice: " + str(ret)


colFam.insert(rowKey, {'money':u'u20AC0.99'})


print "after insert: " + str(colFam.get(rowKey));

Below is the script output.


Reference:

1. Pycassa documentation: http://pycassa.github.com/pycassa/

Get Disk Space in Python–using statvfs

Linux command df is used to report file system disk space usage. A sample output of the df command is as below,

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/sda1              5597680   3732772   1580560  71% /

udev                    254684       232    254452   1% /dev

none                    254684       360    254324   1% /dev/shm

none                    254684        96    254588   1% /var/run

none                    254684         0    254684   0% /var/lock

none                    254684         0    254684   0% /lib/init/rw

/dev/sr0                 32780     32780         0 100% /media/cdrom0

Sometimes we want to get similar information in our program. Linux system has a library function called statvfs. Python has a wrapper for this function. It takes an input path and returns a structure with information about the mounted disk containing the input file.

Below is a sample python program,

#!/usr/bin/python

import os

disk = os.statvfs("/var/")

print "preferred file system block size: " + str(disk.f_bsize)

print "fundamental file system block size: " + str(disk.f_frsize)

print "total number of blocks in filesystem: " + str(disk.f_blocks)

print "total number of free blocks: " + str(disk.f_bfree)

print "free blocks available to non-super user: " + str(disk.f_bavail)

print "total number of file nodes: " + str(disk.f_files)

print "total number of free file nodes: " + str(disk.f_ffree)

print "free nodes available to non-super user: " + str(disk.f_favail)

print "flags: " + str(disk.f_flag)

print "miximum file name length: " + str(disk.f_namemax)

print "~~~~~~~~~~calculation of disk usage:~~~~~~~~~~"

totalBytes = float(disk.f_bsize*disk.f_blocks)

print "total space: %d Bytes = %.2f KBytes = %.2f MBytes = %.2f GBytes" % (totalBytes, totalBytes/1024, totalBytes/1024/1024, totalBytes/1024/1024/1024)

totalUsedSpace = float(disk.f_bsize*(disk.f_blocks-disk.f_bfree))

print "used space: %d Bytes = %.2f KBytes = %.2f MBytes = %.2f GBytes" % (totalUsedSpace, totalUsedSpace/1024, totalUsedSpace/1024/1024, totalUsedSpace/1024/1024/1024)

totalAvailSpace = float(disk.f_bsize*disk.f_bfree)

print "available space: %d Bytes = %.2f KBytes = %.2f MBytes = %.2f GBytes" % (totalAvailSpace, totalAvailSpace/1024, totalAvailSpace/1024/1024, totalAvailSpace/1024/1024/1024)

totalAvailSpaceNonRoot = float(disk.f_bsize*disk.f_bavail)

print "available space for non-super user: %d Bytes = %.2f KBytes = %.2f MBytes = %.2f GBytes " % (totalAvailSpaceNonRoot, totalAvailSpaceNonRoot/1024, totalAvailSpaceNonRoot/1024/1024, totalAvailSpaceNonRoot/1024/1024/1024) 

The first part of the program print out each field of the returned structure. The second part of this program print out the disk space information. The output in my Ubuntu Linux gives the following output,

preferred file system block size: 4096

fundamental file system block size: 4096

total number of blocks in filesystem: 1399420

total number of free blocks: 465629

free blocks available to non-super user: 394542

total number of file nodes: 355520

total number of free file nodes: 186598

free nodes available to non-super user: 186598

flags: 0

miximum file name length: 255

~~~~~~~~~~calculation of disk usage:~~~~~~~~~~

total space: 5732024320 Bytes = 5597680.00 KBytes = 5466.48 MBytes = 5.34 GBytes

used space: 3824807936 Bytes = 3735164.00 KBytes = 3647.62 MBytes = 3.56 GBytes

available space: 1907216384 Bytes = 1862516.00 KBytes = 1818.86 MBytes = 1.78 GBytes

available space for non-super user: 1616044032 Bytes = 1578168.00 KBytes = 1541.18 MBytes = 1.51 GBytes 

How to Deploy Python Program without Source Code–by Compilation

Python is an interpreted programming language. It doesn’t require compilation to run. However, there’re situations we want to hide the python code and deploy the executable only.

One way to do this is to compile the python py file into pyc file, and deploy the pyc file. Below is a hello world python program,

#!/usr/bin/python
print "hello world"

Save the code to test.py, and make sure the file is executable (sudo chmod +x test.py). To compile the program, we’ll need another python program,

#!/usr/bin/python
import py_compile
py_compile.compile("test.py")

You can compile the program by running the second python program. Suppose the code is saved to compile.py. Enter the following command,

sudo chmod +x compile.py
./compile.py

There’ll be a test.pyc file created.

To execute the pyc file, enter the command,

python test.pyc

 

This will achieve the same effect as

./test.py

 

Upon deployment, one can simply copy the pyc file instead of the source code py file.

Serial Port Communication in Python

pyserial is a python module that allows one to access serial port. It’s easy to use and one can start test serial port communication in minutes.

1. Install pyserial

If your machine doesn’t have pyserial module installed, you can install the module using easy_install.

sudo easy_install pyserial

In case you don’t have easy_install installed, you can install it by entering the following command,

sudo apt-get install python-setuptools

Then you can run the command above to install pyserial.

2. A Sample Program

The sample program use pyserial to communicate with a modem device with its serial port interface at /dev/ttyUSB0 in Ubuntu Linux.

#!/usr/bin/python
import serial, time
#initialization and open the port
#possible timeout values:
#    1. None: wait forever, block call
#    2. 0: non-blocking mode, return immediately
#    3. x, x is bigger than 0, float allowed, timeout block call
ser = serial.Serial()
ser.port = "/dev/ttyUSB0"
#ser.port = "/dev/ttyS2"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
#ser.timeout = None          #block read
ser.timeout = 0             #non-block read
#ser.timeout = 2              #timeout block read
ser.xonxoff = False     #disable software flow control
ser.rtscts = False     #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False       #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2     #timeout for write
try: 
    ser.open()
except Exception, e:
    print "error open serial port: " + str(e)
    exit()
if ser.isOpen():
    try:
        ser.flushInput() #flush input buffer, discarding all its contents
        ser.flushOutput()#flush output buffer, aborting current output 
                     #and discard all that is in buffer
        #write data
        ser.write("AT+CSQ=?x0D")
        print("write data: AT+CSQ=?x0D")
        time.sleep(0.5)  #give the serial port sometime to receive the data
        numOfLines = 0
        while True:
            response = ser.readline()
            print("read data: " + response)
            numOfLines = numOfLines + 1
            if (numOfLines >= 5):
                break
        ser.close()
    except Exception, e1:
        print "error communicating...: " + str(e1)
else:
    print "cannot open serial port "

 

The program send out AT commands to query modem signal strength. If you want to know more about modem AT commands, refer to post here.

If you set the timeout as 2, the readline() method is blocking call with timeout, the output will be as below,

write data: AT+CSQ=?
read data: AT+CSQ=?

read data: +CSQ: (0-31,99),(99)

read data: 

read data: OK

read data: 

If you set the timeout as None, the readline() method is non-blocking call, the output is,

write data: AT+CSQ=?
read data: AT+CSQ=?

read data: +CSQ: (0-31,99),(99)

read data: 

read data: OK


Note that there is less lines of output, program hangs and cannot exit.

If you set the timeout as 0, the readline() method will return immediately, the output is,

write data: AT+CSQ=?
read data: AT+CSQ=?

read data: +CSQ: (0-31,99),(99)

read data: 

read data: OK

read data: 

 

Reference:

pyserial documentation: http://pyserial.sourceforge.net/pyserial.html

Linux Get udev Device Information in Python–pyudev

udev is the device manager for the Linux kernel. It consists of 3 parts, libudev, the library that provides access to device information; the daemon udevd, manages the virtual file system normally mounted at /dev, running in user space; and udevadm, an utility tool for diagnostics.

This entry covers how to access the device information through udev in Python.

1. Install pyudev

A python module pyudev needs to be installed first. One can use easy_install to install python module. If easy_install is not available on your system, run the following command (using Ubuntu as example),

sudo apt-get install python-setuptools

 

Then type the following command to install pyudev,

sudo easy_install pyudev

pyudev is a python binding to libudev. One can import pyudev namespace and then use classes and functions in this library. The most important object in pyudev is Device, which gives you access to all the information about a device.

2. A Sample Python Program

Below is a sample program that uses pyudev to query usb device information. One can extend it or modify it easily to suit his/her own needs.

If a sysfs path is provided, the program will retrieve the information for the particular device; otherwise, the program loop through all usb devices and output information for every one of them.

#!/usr/bin/python
import pyudev, sys
from datetime import datetime

def log(level, msg):
    #strToWrite = str(datetime.now()) + ":" + str(msg)
    i = 0
    strToWrite = ""
    while True:
        if (i >= level):
            break
        strToWrite = strToWrite + "  "
        i = i + 1
    strToWrite = strToWrite + str(msg)
    print strToWrite

def getInfoForADevice(aDevice, level):
    msgStr = "*****************************************************"
    log(level, msgStr)
    msgStr = "sys_path: %s:" % aDevice.sys_path
    log(level, msgStr)
    msgStr = "device_path: " + aDevice.device_path
    log(level, msgStr)
    msgStr = "sys_name: " + aDevice.sys_name
    log(level, msgStr)
    msgStr = "subsystem: " + str(aDevice.subsystem)
    log(level, msgStr)
    msgStr = "driver: " + str(aDevice.driver)
    log(level, msgStr)
    msgStr = "device type: " + str(aDevice.device_type)
    log(level, msgStr)
    msgStr = "device node: " + str(aDevice.device_node)
    log(level, msgStr)
    msgStr = "----------ATTRIBUTES----------"
    log(level, msgStr)
    for attrName, attrValue in aDevice.attributes.iteritems():
        msgStr = attrName + ": " + str(attrValue)
        log(level, msgStr)
    for aChildDevice in aDevice.children:
        getInfoForADevice(aChildDevice, level + 1)

if __name__ == '__main__':
    global context
    context = pyudev.Context()
    if (len(sys.argv) == 1):
        devices = context.list_devices(subsystem="usb") 
        #devices = context.list_devices()
        if not devices:
            print "no device found"
        for aDevice in devices:
            getInfoForADevice(aDevice, 0) 
    else:
        aDevice = pyudev.Device.from_path(context, sys.argv[1])
        getInfoForADevice(aDevice, 0)

        

The program first get a list of usb Device objects,  and access the information of each one by calling method getInfoForADevice(). Notice that this method is recursive and the child device information is also accessed.

You can redirect the output to a file first and examine it later by entering the following command,

./udev_sample.py > output.txt

 

If you want to query information for a specific device, following the format below,

./udev_sample.py <sys_path>

An example is,

./udev_sample.py /sys/devices/pci0000:00/0000:00:06.0/usb2/2-1/2-1:1.0

 

References:

pyudev documentation: http://packages.python.org/pyudev/

 

 
 

Named Pipe in Linux with a Python Example

Pipe is a simple FIFO communication channel used for one-way Inter-Process Communication (IPC). Typically a starting process creates a pipe, and one or more processes are spawned to receive messages and form a pipeline. As Pipe is a one-way IPC, it normally requires two pipes for two-way communication.

In Linux, pipes are often created by using the pipe system call, which creates a pair of file descriptors, one for reading (receiver) and one for writing (sender). In Linux shell, the “|” character is used to create pipe.

Named Pipe is an extension to traditional pipe. Pipe exists anonymously only when the process is running, while named pipe is persistent and should be deleted when it’s not needed.

Named pipe uses file system. It’s created using mkfifo() and mknod(). Once it’s created, two separate processes can access the pipe by name, one as a reader, the other one as a writer.

A named pipe supports blocked read and write operations by default: if a process opens the file for reading, it is blocked until another process opens the file for writing, and vice versa. However, it is possible to make named pipes support non-blocking operations by specifying the O_NONBLOCK flag.

A named pipe must be opened either read-only or write-only. It cannot be opened for read-write because it’s a one-way channel. You’ll need to create two named pipes to establish a two-way communication.

Below is an example of using Named Pipe for synchronized communication in Python,

pipe_test_1.py


#!/usr/bin/python
import cPickle
import os
#communicate with another process through named pipe
#one for receive command, the other for send command
wfPath = "./p1"
rfPath = "./p2"
wp = open(wfPath, 'w')
wp.write("P1: How are you?")		
wp.close()
rp = open(rfPath, 'r')
response = rp.read()
print "P1 hear %s" % response
rp.close()
wp = open(wfPath, 'w')
wp.write("P1: I'm fine too.")		
wp.close()


pipe_test_2.py


#!/usr/bin/python
import cPickle
import os
#communicate with another process through named pipe
#one for receive command, the other for send command
rfPath = "./p1"
wfPath = "./p2"
try:
    os.mkfifo(wfPath)
    os.mkfifo(rfPath)
except OSError:
    pass
rp = open(rfPath, 'r')
response = rp.read()
print "P2 hear %s" % response
rp.close()
wp = open(wfPath, 'w')
wp.write("P2: I'm fine, thank you! And you?")		
wp.close()
rp = open(rfPath, 'r')
response = rp.read()
print "P2 hear %s" % response
rp.close()


To run this example,

1. Open a terminal, start pipe_test_2.py by typing: ./pipe_test_2.py

2. Open another terminal, start pipe_test_1.py by typing: ./pipe_test_1.py

The output should be,

1. at terminal running pipe_test_2.py:

P2 hear P1: How are you?

P2 hear P1: I’m fine too.

2. at terminal running pipe_test_1.py:

P1 hear P2: I’m fine, thank you! And you?

As you can imagine, the two little programs can be converted to a simple chat program by adding some looping structure.

Reference: http://developers.sun.com/solaris/articles/named_pipes.html

Side Note: first draft on Apr 21 2011.