How to Use the Paho MQTT Client in Python with Examples
Eclipse Paho, like the Eclipse Mosquitto MQTT broker, is also an open-source project. It offers MQTT clients support for various programming languages and is considered the standard for MQTT client functionality.
The project name, “Paho,” meaning “communicate with everyone,” was chosen by its creators to highlight its multi-language capability.
In this tutorial, I will demonstrate how to use the Paho Python client with the Pro Edition for Eclipse Mosquitto™ MQTT broker. You do not require any additional prerequisites – simply test it in your internet browser window. Continue reading to find an example code snippet at the end of the tutorial.
How to install the Paho MQTT Python client
To use the Python implementation of the Paho MQTT client, you’ll need a Python execution environment in place. There are different approaches to setting this up.
You can start a ready-to-use environment by clicking this link to follow the approach I want to share. Doing so will launch the Jupyter Notebook in your internet browser with a Python MQTT example code. In the following sections, I will guide you through each step of the process.
This environment is straightforward to use. Click “play,” as shown below, and the selected Python code lines (marked with the blue vertical bar on the left) will run in your browser window.
Another nice feature of the Jupyter Python environment is that when pressing “ctrl+I” for Windows or “command+I” for Mac (or right-clicking “Show Contextual Help”), you can get information about the specific function call depending on your cursor location.
If you plan to prepare or use your Python environment, install the Paho MQTT client using the Python package tool. For more information, check out this reference.
pip install paho-mqtt
As the picture above shows, Python’s default environment installation always imports and uses the SSL package (import ssl
).
Get your ready-to-use and secure MQTT broker
Of course, you will also need an MQTT broker for this Paho MQTT Python setup. Sign up for a free 14-day trial and verify your email to receive detailed instructions, as shown here. This will give you access to the Pro Edition for Eclipse Mosquitto MQTT broker with an intuitive WebUI setup in minutes.
Create the Python MQTT client object
After following the steps in the previous sections, you should have a Python environment and an MQTT server set up and ready to use. Make sure to create at least one client with the following credentials, as shown here:
Client id: “myPy”
Username: “user”
Password: “password”
Now, let’s create a client object with the name client in Python.
import paho.mqtt.client as mqtt
import ssl
version = '5' # or '3'
mytransport = 'websockets' # or 'tcp'
if version == '5':
client = mqtt.Client(client_id="myPy",
transport=mytransport,
protocol=mqtt.MQTTv5)
if version == '3':
client = mqtt.Client(client_id="myPy",
transport=mytransport,
protocol=mqtt.MQTTv311,
clean_session=True)
The following two sections will provide an additional explanation for the code snippet above.
MQTT protocol version and the introduction of expiry intervals
MQTT is a standard communication protocol that currently has two versions: 3.1.1 and 5.0. During the Python MQTT configuration process, you can set which version to use by specifying the protocol parameter and choosing either the MQTTv311 or MQTTv5 value from the Paho client library (as shown in the code above).
Note: Version 5.0 was introduced in 2018 and released in March 2019, so it is yet to be part of the ISO standard.
Despite this, the MQTT protocol has undergone significant improvements from version 3.1.1 to 5.0. One noteworthy improvement is how the protocol handles session expiry. This change can be advantageous for TLS encryption because it reduces traffic overhead by reusing session data when deploying MQTT version 5.0. For more details, you can refer to the MQTT TLS article.
Suppose the default clean_session
flag is set to true (see the code snippet above) in version 3.1.1. In this case, the data of every session (including outstanding messages, subscriptions, and TLS handshakes) clears if the keepalive
period (the default value is 60 seconds) is up. This happens when there is no communication between a client and a broker. Check out this blog post to learn more about the CONNECT and CONNACK parameters required for establishing an MQTT connection.
With MQTT version 5.0, the clean_session
flag is split into two flags:
- A clean start flag, indicating that the session should start without using existing session data
- A SessionExpiryInterval flag defines how long to retain the session after a disconnect (see later in the “Configure callbacks and connect a client to your broker” section).
Setting the clean_start
flag to 1 and SessionExpiryInterval to 0 is equivalent to setting clean_session
to 1 in MQTT v3.1.1. The MessageExpiryInterval
, explained in the “Publish messages with the Paho MQTT client in Python” section, enables the use of an expiry interval for the so-called Last Will messages published with the retain flag set to 1 (“last will”). After the MessageExpiryInterval
, the lastWillMessage
will be dismissed. More information about implementing the lastWill parameter for the Mosquitto broker can be found here. Additionally, Pro Mosquitto fully supports the MessageExpiryInterval
, which has been available since version 5.0. It enables the implementation of application-specific settings and boosts functionality.
Examples of “last will” usage
Here is an example to better understand how to use “last will” messages.
Imagine that your IoT infrastructure includes thousands of connected IoT clients like cars, trucks, or other assets with a high probability of going offline for minutes or even weeks. In such cases, messages (e.g., about traffic jams) must have a short expiry interval. After a client reconnects, it may take up to several weeks (after going offline) to deliver other notices or updates.
The SessionExpiryInterval
setting is helpful for choosing between reducing traffic overhead and increasing information security. Imagine an IoT device with low computing performance, energy consumption, and traffic volume. Such a device may have an unstable or irregular network connection and require reconnection.
With a very short SessionExpiryInterval
on every reconnection, you may need to execute a TLS handshake and certificate exchange. This would be the most secure setting to prevent issues such as data tampering or leaks.
For further improvements to the IoT protocol, refer to the documentation here. The Paho MQTT Python client supports the use of all named properties.
Choosing an MQTT transport layer
You must choose a transport layer as the second step for creating a client object.
Pro Mosquitto supports both WebSocket and TCP transport layers, which is an advantage of hosted MQTT brokers. WebSockets use the HTTP protocol and offer benefits such as being firewall-friendly, and compatible with almost any internet connection. However, the TCP protocol performs better because the communication uses a lower layer — the TCP layer. For more details on setting up MQTT over WebSockets, refer to this article.
For this demo, I use a publicly available Python environment from mybinder.org, which requires WebSockets to communicate with the MQTT broker.
You can test advanced MQTT broker functionalities with our free 14-day cloud or 30-day on-prem Pro Mosquitto trial by following this link.
Configure client authentication
To enable TLS for an MQTT broker and access it, you must set two parameters for the client object in Python: the username/password and the TLS settings.
Below is a code snippet to help you with the process:
client.username_pw_set("user", "password")
client.tls_set(certfile=None,
keyfile=None,
cert_reqs=ssl.CERT_REQUIRED)
The first method calls the username_pw_set
parameter. It’s straightforward and sets the username and password you chose in the “Get your ready-to-use and secure MQTT broker” step above.
The second method is tls_set
, which ensures the communication is encrypted. Setting the parameter cert_reqs
to ssl.CERT_REQUIRED.
ensures that the connection is only established if the MQTT server provides a valid server certificate. This is because you are using the hosted MQTT broker version from Cedalo.
If your device does not support the CA from the Cedalo server, you can download the selfsigned .pem
file here. Use client.tls_set(ca_certs="<path>/pemfile.pem")
to set the correct CA path. As an alternative to username/password, you can use certificate-based authentication and authorization (if your broker supports this). In this case, you must add the parameters certfile
and keyfile
to the path of the corresponding files (client certificate and private key). For more information, refer to the certificate-based authentication and authorization section of the MQTT TLS configuration guide.
Configure callbacks and connect a client to your broker
Now, you are almost ready to connect to the broker. However, you must first define at least one callback that handles incoming MQTT messages on subscribed topics. To do this, the client library has the option to define callback functions. In this example, the callback functions are defined in a separate file with the name mycallbacks
.
The code to help you set the essential callbacks is as follows:
import mycallbacks
client.on_message = mycallbacks.on_message;
client.on_connect = mycallbacks.on_connect;
client.on_publish = mycallbacks.on_publish;
client.on_subscribe = mycallbacks.on_subscribe;
The callback function on_message
is defined as follows and publishes the information about the received message. The other optional callbacks in this example print out verbose information.
def on_message(client, userdata, message, properties=None):
print(" Received message " + str(message.payload)
+ " on topic '" + message.topic
+ "' with QoS " + str(message.qos))
Now, you are ready to connect to the broker. Keep in mind that the connect method call differs depending on the MQTT protocol version. Please refer to the ‘MQTT protocol versions’ section above for details. Nevertheless, you have to set the communication port according to the chosen transport layer. For WebSocket, use port 443; and for TCP, use port 8883. Once you establish a successful connection to the broker, the prepared example will print out the callback message (see the picture with the area marked in red).
broker = 'YOUR-BROKER-ADDRESS' # eg. choosen-name-xxxx.cedalo.cloud
myport = 443
if version == '5':
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
properties=Properties(PacketTypes.CONNECT)
properties.SessionExpiryInterval=30*60 # in seconds
client.connect(broker,
port=myport,
clean_start=mqtt.MQTT_CLEAN_START_FIRST_ONLY,
properties=properties,
keepalive=60);
elif version == '3':
client.connect(broker,port=myport,keepalive=60);
client.loop_start();
The code should run smoothly up to this point. However, possible issues may arise when attempting to connect. The table below outlines how to troubleshoot possible connection failures.
Print out / error | Possible Remedy |
Name or service not known | The broker’s name/address is probably incorrect. Use the name/URL from the “Getting Started” email. |
Timed out | Either the broker did not respond or you used the wrong port number. Check the transport (WebSocket vs.TCP) and port number. If you are unsure about the firewall and connection, choose WebSocket and port number 443. |
Connection Refused OR Authentication failed | Check the client credentials: ID, username, password, and whether the client credentials are set up in the broker. |
If you experience further issues within the web-based Python environment, restarting the kernel is recommended. To do so, select kernel in the menu, then ->Restart kernel, and start the code execution again from the top.
Finally, the client method loop_start() ensures the connection maintains the “online” status. This allows you to publish MQTT messages and subscribe to topics, as shown in the following sections. The MQTT subscribe blog post explains how MQTT subscribe works and provides relevant Mosquitto examples.
Test the full potential of the open-source Mosquitto MQTT broker with the Pro version’s advanced features. Sign up for a free 14-day cloud or 30-day on-premises trial.
Subscribe to topics with the Paho MQTT client
With the steps above complete, you can now easily subscribe to topics on the broker to which the client has access. To enable the subscription, call the client method _subscribe_
to subscribe to the required topic and set the optional _quality of service_
parameter. Check out the MQTT QoS article to learn more about it.
mytopic = 'topic/important'
client.subscribe(mytopic,2);
Let’s use the same topic to publish messages so you can see how to receive them.
Publish messages with the Paho MQTT client in Python
To publish messages on topics, you need to call the method to publish on the specific topic. You must also define the payload and the optional quality of service parameter. The following code lines show the case for MQTT version 5.0, which includes the option to specify the MessageExpiryInterval
as mentioned in the section “Create the Python MQTT client object” above.
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
properties=Properties(PacketTypes.PUBLISH)
properties.MessageExpiryInterval=30 # in seconds
client.publish(mytopic,'Cedalo Mosquitto is awesome',2,properties=properties);
Here are some sample outputs from the browser-based Python environment.
Thanks to the connected callback functions, you will see the printout for publishing and receiving. The time difference, marked red in the figure above, is around ten milliseconds, indicating a round trip time for the messages.
In conclusion, any client implementation will only use one connection instance, reuse it, and if not needed anymore, disconnect it by calling disconnect()
.
How to publish messages using the utility function
You can use the ‘paho.mqtt.publish’
module to publish MQTT messages in Python. Two main functions are available.
1. ‘publish.single’
import paho.mqtt.publish as publish
publish.single(topic, payload=None, qos=0, retain=False, hostname="localhost",
port=1883, client_id="", keepalive=60, will=None, auth=None,
tls=None, protocol=mqtt.MQTTv31)
This function connects to an MQTT broker, sends a message to a specified topic, and then disconnects smoothly. Most connection parameters are optional. For example:
publish.single('encyclopedia/temperature', payload='hot')
The client documentation usually provides detailed descriptions of the `will`
, `auth`
, and `tls`
parameters.
2. `publish.multiple`
publish.multiple(msgs, hostname="localhost", port=1883, client_id="", keepalive=60,
will=None, auth=None, tls=None, protocol=mqtt.MQTTv31)
This function is similar to `publish.single`
but allows you to publish multiple messages at once. The `msgs`
parameter represents a list of MQTT messages that need to be published.
msg = {'topic': "<topic>", 'payload': "<payload>", 'qos': <qos>, 'retain': <retain>}
Does not work with the object “msg” defined.
You need to define it as list (for example):
msgs = [
{'topic': "encyclopedia/temperature", 'payload': "hot", 'qos': 1, 'retain': False},
{'topic': "encyclopedia/humidity", 'payload': "low", 'qos': 1, 'retain': False}
]
publish.multiple(msgs)
If you’re working with PHP and looking for a way to integrate MQTT, check out our guide on how to leverage Mosquitto MQTT Broker in PHP.
Wrap up
This article utilizes the Eclipse Paho MQTT client for Python to publish and receive messages from the Mosquitto MQTT broker.
Additionally, I show and explain the core differences between MQTT protocol versions 3.1.1 and 5.0 as part of the prepared Python environment. Furthermore, I use the Management Center as a GUI to administer client access and monitor the Pro Edition for Eclipse Mosquitto broker.
You can use the code snippets on GitHub for your upcoming projects that utilize the Python Paho client and Mosquitto.
An example connection could look like this:
import paho.mqtt.client as mqtt
import ssl
from datetime import datetime as dt
def on_connect(client, userdata, flags, reason_code, properties=None):
client.subscribe(topic="RXB")
def on_message(client, userdata, message, properties=None):
print(
f"{dt.now()} Received message {message.payload} on topic '{message.topic}' with QoS {message.qos}"
)
def on_subscribe(client, userdata, mid, qos, properties=None):
print(f"{dt.now()} Subscribed with QoS {qos}")
client = mqtt.Client(client_id="clientid", protocol=mqtt.MQTTv311, clean_session=True)
client.on_connect = on_connect
client.on_message = on_message
client.on_subscribe = on_subscribe
client.username_pw_set(username="username", password="password")
client.tls_set(ca_certs="cacerts/isrgrootx1.pem")
client.connect(host="example.cedalo.cloud", port=8883, keepalive=60)
client.loop_forever()
About the author
Dr. Andreas Schiffler is a research professor at the Technical University of Wuerzburg-Schweinfurt in the field of production and data technology in mechanical engineering. In addition to research topics related to 3D metal printing, Dr. Schiffler developed a Kubernetes cluster for the practice-oriented basics of IoT and Industry 4.0 as part of the student training. Before joining the university, he worked in different product development-related positions for Siemens AG and Schaeffler AG.
His hobbies and private activities are mixed to share practical knowledge on topics like home automation driven by MQTT protocol or using open-source CNC controllers for machine tools.