Client-Server

Rserve is currently the default solution when looking for a server solution for R, but rpy2 can be used to develop very easily one’s own server, tailored to answer specific requirements. Such requirements can include for example access restriction, a security model, access to subsets of the R engine, distribution of jobs to other servers, all of which are currently difficult or impossible to achieve with R serve.

The pyRserve package addresses the connection to Rserve from Python, and although it frees one from handling the R server is also constrains one to use Rserve.

Simple socket-based server and client

Server

An implementation of a simplistic socket server listening on a given port for a string to evaluate as R code is straightforward with Python’s SocketServer module.

Our example server will be in a file rpyserve.py, containing the following code.

import SocketServer
import sys
import rpy2.robjects as robjects

class MyTCPHandler(SocketServer.StreamRequestHandler):

    def handle(self):
        # self.rfile is a file-like object created by the handler;
        # we can now use e.g. readline() instead of raw recv() calls
        self.data = self.rfile.readline().strip()

        # verbose server
        print "%s wrote:" % self.client_address[0]
        print self.data

        # evaluate the data passed as a string of R code
        results = robjects.r(self.data)

        # return the result of the evaluation as a string
        # to the client
        self.wfile.write(str(results))


if __name__ == "__main__":
    HOST, PORT = "localhost", int(sys.argv[1])

    # Create the server, binding to localhost on port 9999
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()

Running a server listening on port 9090 is then:

python rpyserve.py 9090

Client

Using Python’s socket module, implementing a client is just as easy. We write the code for ours into a file rpyclient.py:

import socket
import sys

HOST, PORT = sys.argv[1].split(":")
PORT = int(PORT)
data = " ".join(sys.argv[2:])

# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect to server and send data
sock.connect((HOST, PORT))
sock.send(data + "\n")

# Receive data from the server and shut down
received = sock.recv(1024)
sock.close()

print "Sent:     %s" % data
print "Received: %s" % received

Evaluating R code on a local server as defined in the previous section, listening on port 9090 is then:

python rpyclient.py localhost:9090 'R.version'

In this example, the client is querying the R version.