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


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, containing the following code.

import socketserver
import sys
import rpy2.robjects as robjects

class MyTCPHandler(socketserver.StreamRequestHandler):

    def handle(self):
        # verbose server
        print("%s wrote:" % self.client_address[0])

        # self.rfile is a file-like object created by the handler;
        # we can now use e.g. readline() instead of raw recv() calls
        encoding = self.rfile.readline().strip()
        encoding = str(encoding, 'ASCII')
        print('    encoding: %s' % encoding)

        size = int.from_bytes(, 'little')
        print('    size: %i bytes' % size)
        rcv =
        rcv = str(rcv, encoding) 

        # verbose server
        print('    R code string:')

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

        # return the result of the evaluation as a string
        # to the client
        results = bytes(str(results), encoding)
        size_res = len(results).to_bytes(8, 'little')
        print('    Result size: %i' % len(results))
        self.wfile.write(size_res +

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--port', 
    options = parser.parse_args()

    # Create the server, binding to localhost on port 9999
    server = socketserver.TCPServer((options.hostname, options.port),

    print('Server listening on %s:%i' % (options.hostname, options.port))
    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C

Running a server listening on port 9090 is then:

python --hostname localhost


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

import socket
import sys
import locale
import argparse

def send_R_code(rcode, hostname, port):
    Evaluate the R code in `rcode` (on a possibly remote machine)
    # 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((hostname, port))
    size_send = len(rcode).to_bytes(8, 'little')
    sock.send(bytes(encoding, 'ASCII') + b'\n' + \
              size_send + \

    # Receive data from the server and shut down
    size = int.from_bytes(sock.recv(8), 'little') # 64 bits max
    print("    size: %i bytes" % size)
    received = sock.recv(size)
    print("    R output:")
    print(str(received, encoding))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--port',
    options = parser.parse_args()

    # read R code from STDIN
    rcode =
    encoding = locale.getlocale()[1]
    rcode = bytes(rcode, encoding)

    send_R_code(rcode, options.hostname, options.port)

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

echo 'R.version' | python --hostname localhost

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