jsonrpcclient

Send JSON-RPC requests in Python 2.7 and 3.3+.

Guides

jsonrpcclient

jsonrpcclient over HTTP

Send JSON-RPC requests over HTTP.

Installation

$ pip install jsonrpcclient requests

Usage

Set the server details:

>>> from jsonrpcclient.http_server import HTTPServer
>>> server = HTTPServer('http://pets.com/api')

Send a request with send():

>>> server.send({'jsonrpc': '2.0', 'method': 'cat', 'id': 1})

Sending a request is easier with request(). It takes the method, followed by the arguments to the method:

>>> server.request('cat', name='Mittens')

When sending a single request, the return value is the payload (the result part of the JSON-RPC response message).

If you’re not interested in a response, use notify() instead of request().

Batch requests

Send multiple requests in one message:

>>> server.send([{'jsonrpc': '2.0', 'method': 'cat'}, {'jsonrpc': '2.0', 'method': 'dog'}])

Send multiple Request objects:

>>> server.send([Request('cat'), Request('dog')])

Using list comprehension to get the cube of ten numbers:

>>> server.send([Request('cube', i) for i in range(10)])

Unlike single requests, batch requests return the whole JSON-RPC response object, i.e. a list of responses for each request that had an id member.

Note

The server may not support batch requests.

Headers

To customize the HTTP headers, pass a headers argument to HTTPServer:

>>> server = HTTPServer('http://example.com/api', headers={'Content-Type': 'application/json-rpc'})

If no headers are given, the following headers are used:

Content-Type: application/json
Accept: application/json
Authentication

To make authenticated requests, pass an auth argument to HTTPServer:

>>> server = HTTPServer('http://example.com/api', auth=('user', 'pass'))

For more authentication options, see the requests module which handles the authentication.

Note

In addition to headers and authentication, other arguments can allow you to set the timeout, cookies, SSL verification and more. For the full list of options see the request method here.

Exceptions

In the event of a communications problem, the Requests module raises requests.exceptions.RequestException:

try:
    server.request('go')
except requests.exceptions.RequestException as e:
    print(str(e))

The jsonrpcclient library also raises exceptions, for example if the server responded with an error message. The full list of exceptions are here.

Logging

To see the JSON-RPC messages going back and forth, set the logging level to INFO:

import logging
logging.getLogger('jsonrpcclient').setLevel(logging.INFO)

Then add a basic handler:

logging.getLogger('jsonrpcclient').addHandler(logging.StreamHandler())

Or use custom handlers and formats:

request_format = '%(endpoint)s --> %(message)s'
response_format = '%(endpoint)s <-- %(message)s'

# Request log
request_handler = logging.StreamHandler()
request_handler.setFormatter(logging.Formatter(fmt=request_format))
logging.getLogger('jsonrpcclient.server.request').addHandler(
    request_handler)

# Response log
response_handler = logging.StreamHandler()
response_handler.setFormatter(logging.Formatter(fmt=response_format))
logging.getLogger('jsonrpcclient.server.response').addHandler(
    response_handler)

The request format has these fields:

endpoint:The server endpoint, eg. http://example.com/api.
http_headers:The full HTTP headers.
message:The JSON request (the body).

The response format has these fields:

endpoint:The server endpoint, eg. http://example.com/api.
http_code:The HTTP status code received from the server, eg. 400.
http_reason:The description of the status code, eg. BAD REQUEST.
http_headers:The full HTTP headers.
message:The JSON response (the body).

jsonrpcclient

jsonrpcclient over ZeroMQ

Send JSON-RPC requests over ZeroMQ.

Installation

$ pip install jsonrpcclient pyzmq

Usage

Set the server details:

from jsonrpcclient.zmq_server import ZMQServer
server = ZMQServer('tcp://localhost:5555')

Send a request with send():

>>> server.send({'jsonrpc': '2.0', 'method': 'cat', 'id': 1})

Sending a request is easier with request(). It takes the method, followed by the arguments to the method:

>>> server.request('cat', name='Mittens')

When sending a single request, the return value is the payload (the result part of the JSON-RPC response message).

If you’re not interested in a response, use notify() instead of request().

Batch requests

Send multiple requests in one message:

>>> server.send([{'jsonrpc': '2.0', 'method': 'cat'}, {'jsonrpc': '2.0', 'method': 'dog'}])

Send multiple Request objects:

>>> server.send([Request('cat'), Request('dog')])

Using list comprehension to get the cube of ten numbers:

>>> server.send([Request('cube', i) for i in range(10)])

Unlike single requests, batch requests return the whole JSON-RPC response object, i.e. a list of responses for each request that had an id member.

Note

The server may not support batch requests.

Exceptions

In the event of a communications problem, pyzmq raises zmq.ZMQError:

try:
    server.request('go')
except zmq.ZMQError as e:
    print(str(e))

The jsonrpcclient library also raises exceptions, for example if the server responded with an error message. The full list of exceptions are here.

Logging

To see the JSON-RPC messages going back and forth, set the logging level to INFO:

import logging
logging.getLogger('jsonrpcclient').setLevel(logging.INFO)

Then add a basic handler:

logging.getLogger('jsonrpcclient').addHandler(logging.StreamHandler())

Or use custom handlers and formats:

request_format = '%(endpoint)s --> %(message)s'
response_format = '%(endpoint)s <-- %(message)s'

# Request log
request_handler = logging.StreamHandler()
request_handler.setFormatter(logging.Formatter(fmt=request_format))
logging.getLogger('jsonrpcclient.server.request').addHandler(
    request_handler)

# Response log
response_handler = logging.StreamHandler()
response_handler.setFormatter(logging.Formatter(fmt=response_format))
logging.getLogger('jsonrpcclient.server.response').addHandler(
    response_handler)

The request format has these fields:

endpoint:The server endpoint, eg. http://localhost:5555.
message:The JSON request (the body).

The response format has these fields:

endpoint:The server endpoint, eg. http://localhost:5555.
message:The JSON response (the body).

jsonrpcclient

API

HTTPServer

An HTTP server to communicate with, for example:

HTTPServer('http://example.com/api').request('go')
class http_server.HTTPServer(endpoint, **kwargs)
Parameters:
  • endpoint – The server address.
  • kwargs – HTTP headers and other options passed on to the requests module.
DEFAULT_HTTP_HEADERS = {'Accept': 'application/json', 'Content-Type': 'application/json'}
notify(method_name, *args, **kwargs)

Send a JSON-RPC request, without expecting a response.

Parameters:
  • method_name – The remote procedure’s method name.
  • args – Positional arguments passed to the remote procedure.
  • kwargs – Keyword arguments passed to the remote procedure.
Returns:

The payload (i.e. the result part of the response.)

request(method_name, *args, **kwargs)

Send a JSON-RPC request, and get a response.

Parameters:
  • method_name – The remote procedure’s method name.
  • args – Positional arguments passed to the remote procedure.
  • kwargs – Keyword arguments passed to the remote procedure.
Returns:

The payload (i.e. the result part of the response.)

send(request)

Send a request or batch of requests.

Parameters:request – The request to send. If a string, must be valid JSON (double quotes around the identifiers!). Otherwise it must be a json serializable object (list or dict).
validator = <jsonschema.validators.create.<locals>.Validator object>

ZMQServer

A ZeroMQ server to communicate with, for example:

ZMQServer('tcp://hostname:5555').request('go')
class zmq_server.ZMQServer(endpoint, socket_type=3)
Parameters:
  • endpoint – The server address.
  • socket_type – The zeromq socket type. Default is zmq.REQ.
notify(method_name, *args, **kwargs)

Send a JSON-RPC request, without expecting a response.

Parameters:
  • method_name – The remote procedure’s method name.
  • args – Positional arguments passed to the remote procedure.
  • kwargs – Keyword arguments passed to the remote procedure.
Returns:

The payload (i.e. the result part of the response.)

request(method_name, *args, **kwargs)

Send a JSON-RPC request, and get a response.

Parameters:
  • method_name – The remote procedure’s method name.
  • args – Positional arguments passed to the remote procedure.
  • kwargs – Keyword arguments passed to the remote procedure.
Returns:

The payload (i.e. the result part of the response.)

send(request)

Send a request or batch of requests.

Parameters:request – The request to send. If a string, must be valid JSON (double quotes around the identifiers!). Otherwise it must be a json serializable object (list or dict).
validator = <jsonschema.validators.create.<locals>.Validator object>

Requests

These classes make it easy to create JSON-RPC Request objects.

request.Notification

A JSON-RPC Request object, with no id member (meaning no payload data is wanted):

>>> from jsonrpcclient import Notification
>>> Notification('cat')
{'jsonrpc': '2.0', 'method': 'cat'}

The first argument is the method; everything else is arguments to the method:

>>> Notification('cat', 'Mittens', 5)
{'jsonrpc': '2.0', 'method': 'cat', params: ['Mittens', 5]}

Keyword arguments are also acceptable:

>>> Notification('cat', name='Mittens', age=5)
{'jsonrpc': '2.0', 'method': 'cat', 'params': {'name': 'Mittens', 'age': 5}}

If you prefer, call the method as though it was a class attribute:

>>> Notification.cat(name='Mittens', age=5)
{'jsonrpc': '2.0', 'method': 'cat', 'params': {'name': 'Mittens', 'age': 5}}
Parameters:
  • method – The method name.
  • args – Positional arguments.
  • kwargs – Keyword arguments.
Returns:

The JSON-RPC request in dictionary form.

request.Request

A JSON-RPC Request object, with an id member (meaning payload data is wanted):

>>> Request('cat')
{'jsonrpc': '2.0', 'method': 'cat', 'id': 1}

An auto-incremented id is used, so each request has a unique id:

>>> Request('cat')
{'jsonrpc': '2.0', 'method': 'cat', 'id': 2}

Use request_id to specify the id to use:

>>> Request('cat', request_id='Request #1')
{'jsonrpc': '2.0', 'method': 'cat', 'id': 'Request #1'}
Parameters:
  • method – The method name.
  • args – Positional arguments.
  • kwargs – Keyword arguments.
Returns:

The JSON-RPC request in dictionary form.

ID Iterators

By default the request id is a decimal number which increments for each request. Use a different format by setting Request.id_iterator:

>>> from jsonrpcclient.request import Request
>>> from jsonrpcclient.id_iterators import random_iterator
>>> Request.id_iterator = random_iterator()
>>> Request('go')
{'jsonrpc': '2.0', 'method': 'go', 'id': 'fubui5e6'}
id_iterators.hex_iterator(start=1)

Incremental hexadecimal numbers.

e.g. ‘1’, ‘2’ .. ‘9’, ‘a’, ‘b’, etc.

Request.id_iterator = hex_iterator()
id_iterators.uuid_iterator()

Unique uuid ids.

e.g. ‘9bfe2c93-717e-4a45-b91b-55422c5af4ff’

Request.id_iterator = uuid_iterator()
id_iterators.random_iterator(length=8, chars='0123456789abcdefghijklmnopqrstuvwxyz')

A random string. Not unique, but has around 1 in a million chance of collision with default values.

e.g. ‘fubui5e6’

Request.id_iterator = random_iterator(16, 'abc123')
Parameters:
  • length – Length of the random string.
  • chars – The characters to randomly choose from.

Exceptions

These exceptions are raised when processing responses from the server. For example, if the response was garbage and could not be parsed, ParseResponseError is raised.

To handle them, use a try-block when calling notify or request:

try:
    server.notify('go')
except JsonRpcClientError as e:
    print(str(e))
exception jsonrpcclient.exceptions.JsonRpcClientError

Bases: Exception

Base class for the other exceptions.

exception jsonrpcclient.exceptions.ParseResponseError

Bases: jsonrpcclient.exceptions.JsonRpcClientError

The response was not valid JSON.

exception jsonrpcclient.exceptions.ReceivedErrorResponse(code, message, data)

Bases: jsonrpcclient.exceptions.JsonRpcClientError

Raised if a single JSON-RPC error response object is received. This is not raised for batch requests.

This error means one of two things:

  1. There was a problem with the request.
  2. There was a problem with the application at the receiving end.

To see information about the error, catch the exception:

from jsonrpcclient.exceptions import JsonRpcClientError, \
    ReceivedErrorResponse
try:
    server.notify('go')
except ReceivedErrorResponse as e:
    print(e.code, e.message, e.data)
except JsonRpcClientError as e:
    print(str(e))