### Navigation

- index
- modules |
- next |
- previous |
- home|
- search|
- API »

# Devices in PyZMQ

See also

ØMQ Guide Device coverage.

ØMQ has a notion of Devices - simple programs that manage a send-recv pattern for connecting two or more sockets. Being full programs, devices include a `while(True)` loop and thus block execution permanently once invoked. We have provided in the `devices` subpackage some facilities for running these devices in the background, as well as a custom three-socket MonitoredQueue device.

## BackgroundDevices

It seems fairly rare that in a Python program one would actually want to create a zmq device via `device()` in the main thread, since such a call would block execution forever. The most likely model for launching devices is in background threads or processes. We have provided classes for launching devices in a background thread with `ThreadDevice` and via multiprocessing with `ProcessDevice`. For threadsafety and running across processes, these methods do not take Socket objects as arguments, but rather socket types, and then the socket creation and configuration happens via the BackgroundDevice’s `x_in()` proxy methods. For each configuration method (bind/connect/setsockopt), there are proxy methods for calling those methods on the Socket objects created in the background thread or process, prefixed with ‘in_’ or ‘out_’, corresponding to the in_socket and out_socket:

    from zmq.devices.basedevice import ProcessDevice

    pd = ProcessDevice(zmq.QUEUE, zmq.REP, zmq.REQ)
    pd.bind_in('tcp://*:12345')
    pd.connect_out('tcp://127.0.0.1:12543')
    pd.setsockopt_in(zmq.IDENTITY, 'REP')
    pd.setsockopt_out(zmq.IDENTITY, 'REQ')
    pd.start()
    # it will now be running in a background process

## MonitoredQueue

One of ØMQ’s builtin devices is the `QUEUE`. This is a symmetric two-socket device that fully supports passing messages in either direction via any pattern. We saw a logical extension of the `QUEUE` as one that behaves in the same way with respect to the in/out sockets, but also sends every message in either direction also on a third monitor socket. For performance reasons, this `monitored_queue()` function is written in Cython, so the loop does not involve Python, and should have the same performance as the basic `QUEUE` device.

One shortcoming of the `QUEUE` device is that it does not support having `XREP` sockets as both input and output. This is because `XREP` sockets, when they receive a message, prepend the `IDENTITY` of the socket that sent the message (for use in routing the reply). The result is that the output socket will always try to route the incoming message back to the original sender, which is presumably not the intended pattern. In order for the queue to support an XREP-XREP connection, it must swap the first two parts of the message in order to get the right message out the other side.

To invoke a monitored queue is similar to invoking a regular ØMQ device:

    from zmq.devices.monitoredqueue import monitored_queue
    ins = ctx.socket(zmq.XREP)
    outs = ctx.socket(zmq.XREQ)
    mons = ctx.socket(zmq.PUB)
    configure_sockets(ins,outs,mons)
    monitored_queue(ins, outs, mons, in_prefix='in', out_prefix='out')

The in_prefix and out_prefix default to ‘in’ and ‘out’ respectively, and a PUB socket is most logical for the monitor socket, since it will never receive messages, and the in/out prefix is well suited to the PUB/SUB topic subscription model. All messages sent on mons will be multipart, the first part being the prefix corresponding to the socket that received the message.

`devices.monitoredqueuedevice` contains subclasses of BackgroundDevices for launching a monitored queue in the background, which function just like the base BackgroundDevice objects, but add x_mon methods for configuring the monitor socket.

### Navigation

- index
- modules |
- next |
- previous |
- home|
- search|
- API »