Die Änderung der Callback API Version in Paho MQTT 2.0 ist der häufigste Grund, warum Python-MQTT-Skripte nach einem pip install --upgrade plötzlich nicht mehr funktionieren. Dieser Leitfaden erklärt genau, was sich in paho-mqtt 2.0 geändert hat, liefert Ihnen die einzeilige Lösung für den Fehler und führt Sie dann durch die Migration jedes Callbacks auf die empfohlenen VERSION2-Signaturen. Am Ende haben Sie ein vollständiges, lauffähiges Beispiel mit Verbindung zu broker.connectmq.com, das Sie als Vorlage nutzen können.
Die Fehler, die Sie wahrscheinlich sehen
Sind Sie über eine Suchmaschine hier gelandet, haben Sie höchstwahrscheinlich einen dieser Fehler:
ValueError: Unsupported callback API version: version 2.0 added a callback_api_version, see docs/migrations.rst for details
TypeError: Client.__init__() missing 1 required positional argument: 'callback_api_version'
DeprecationWarning: Callback API version 1 is deprecated, update to latest version
TypeError: on_connect() takes 4 positional arguments but 5 were given
Die ersten beiden entstehen, wenn der Client auf die 1.x-Art erzeugt wird. Der ValueError tritt auf, wenn Sie eine Client ID als erstes Positionsargument übergeben, wie in mqtt.Client("my-device"), denn diese Position gehört nun der Callback API Version. Der dritte ist eine Warnung, dass Sie die alte API ausdrücklich gewählt haben. Der vierte erscheint, nachdem Sie auf VERSION2 umgestellt, aber einen Callback mit der alten Parameterzahl belassen haben.
Was sich in paho-mqtt 2.0 geändert hat
Version 2.0 des Eclipse-Paho-Python-Clients, Anfang 2024 erschienen, war das erste Major-Release seit Jahren. Die zentrale Änderung: Callbacks sind jetzt versioniert. In 1.x unterschieden sich die an Callbacks übergebenen Parameter zwischen MQTT 3.1.1 und MQTT 5, und manche verwendeten einfache Integer, andere Reason-Code-Objekte. Version 2 vereinheitlicht das: Jeder Callback erhält unabhängig von der Protokollversion dieselben Parameter, und Ergebniscodes sind immer ReasonCode-Objekte.
Damit neue Signaturen bestehenden Code nicht stillschweigend brechen, verlangen die Maintainer eine ausdrückliche Wahl. Das erste Argument von Client() ist jetzt callback_api_version, mit zwei möglichen Werten:
| Wert | Verhalten | Empfohlen? |
|---|---|---|
CallbackAPIVersion.VERSION1 |
Alte Callback-Signaturen aus 1.x, gibt eine Deprecation-Warnung aus | Nur als vorübergehende Brücke |
CallbackAPIVersion.VERSION2 |
Neue einheitliche Signaturen, überall ReasonCode-Objekte |
Ja, für allen neuen und migrierten Code |
Weitere nennenswerte Änderungen in 2.0 sind der Wegfall der Unterstützung für Python 2.7 und sehr alte Python-3-Versionen sowie die Umbenennung der Klasse ReasonCodes in ReasonCode. Die vollständige Liste finden Sie in den offiziellen Migrationshinweisen von paho-mqtt.
Lösung 1: Die einzeilige Brücke (VERSION1)
Ist die Produktion ausgefallen, etwa ein Edge-Gateway, das nach einem Update keine Maschinendaten mehr aus der Halle liefert, und muss sofort wieder laufen, weisen Sie paho an, das alte Verhalten beizubehalten:
import paho.mqtt.client as mqtt
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="my-device")
Alle bestehenden Callbacks funktionieren unverändert weiter. Sie sehen die Deprecation-Warnung, die daran erinnert, dass VERSION1 in einem künftigen Major-Release entfernt wird. Betrachten Sie das als Pflaster, nicht als Lösung.
Ein alternatives Pflaster ist das Fixieren der alten Bibliothek mit pip install "paho-mqtt<2.0". Das funktioniert, blockiert aber Sicherheits- und Fehlerkorrekturen und kollidiert gern mit anderen Paketen, die bereits 2.x voraussetzen. Ziehen Sie das VERSION1-Flag dem Fixieren vor und planen Sie die echte Migration.
Lösung 2: Auf Version 2 der Paho MQTT 2.0 Callback API migrieren
Die echte Lösung besteht darin, VERSION2 zu übergeben und die Callback-Signaturen anzupassen. Hier alle Callbacks im direkten Vergleich:
| Callback | Signatur 1.x / VERSION1 | Signatur VERSION2 |
|---|---|---|
on_connect |
(client, userdata, flags, rc) |
(client, userdata, flags, reason_code, properties) |
on_disconnect |
(client, userdata, rc) |
(client, userdata, disconnect_flags, reason_code, properties) |
on_subscribe |
(client, userdata, mid, granted_qos) |
(client, userdata, mid, reason_code_list, properties) |
on_unsubscribe |
(client, userdata, mid) |
(client, userdata, mid, reason_code_list, properties) |
on_publish |
(client, userdata, mid) |
(client, userdata, mid, reason_code, properties) |
on_message |
(client, userdata, message) |
unverändert |
on_log |
(client, userdata, level, buf) |
unverändert |
Unter VERSION1 mit MQTT 5 hatten einige davon bereits zusätzliche Parameter; VERSION2 beseitigt diesen Unterschied – genau darum geht es bei der Änderung.
Migrations-Checkliste
Arbeiten Sie Ihren Code in dieser Reihenfolge durch:
- Ändern Sie jeden Aufruf
mqtt.Client(...)inmqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=..., ...)und übergeben Sie alle anderen Argumente als Schlüsselwortargumente. - Ergänzen Sie
propertiesinon_connectund benennen Siercinreason_codeum. Ersetzen Sierc == 0durchnot reason_code.is_failure(der Vergleich mit Integern funktioniert weiterhin, das Attribut liest sich aber besser). - Ersetzen Sie
flags["session present"]durchflags.session_present. - Geben Sie
on_disconnectden neuen Parameterdisconnect_flagssowieproperties. - Ersetzen Sie in
on_subscribegranted_qosdurchreason_code_listund prüfen Sie jeden Eintrag: Erfolgscodes haben Werte von 0 bis 2 (die gewährte QoS), bei Fehlern istis_failuregesetzt. - Ergänzen Sie
reason_codeundpropertiesinon_publishundon_unsubscribe. - Durchsuchen Sie die Codebasis nach
ReasonCodesund ändern Sie es inReasonCode. - Führen Sie Ihre Tests mit Warnungen als Fehler aus (
python -W error::DeprecationWarning), um zu belegen, dass kein VERSION1-Client übrig ist.
Ein vollständiges VERSION2-Beispiel
Dieses Skript nutzt alle gängigen Callbacks mit den neuen Signaturen. Ersetzen Sie k7f3q2 durch eine eigene Zufallszeichenfolge, damit Sie keine Topics mit anderen Nutzern des öffentlichen MQTT-Brokers teilen (er ist für Tests gedacht, nicht für Produktionsdaten):
import time
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
PREFIX = "connectmq/demo/k7f3q2"
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Connect failed: {reason_code}")
return
print(f"Connected (session present: {flags.session_present})")
client.subscribe(f"{PREFIX}/#", qos=1)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
for rc in reason_code_list:
print("Subscribe rejected:" if rc.is_failure else "Granted QoS:", rc)
def on_publish(client, userdata, mid, reason_code, properties):
print(f"Publish {mid} acknowledged: {reason_code}")
def on_message(client, userdata, msg):
print(f"{msg.topic}: {msg.payload.decode()}")
def on_disconnect(client, userdata, disconnect_flags, reason_code, properties):
print(f"Disconnected: {reason_code}")
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=f"migrate-{uuid.uuid4().hex[:8]}",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_publish = on_publish
client.on_message = on_message
client.on_disconnect = on_disconnect
client.connect(BROKER, 1883, keepalive=60)
client.loop_start()
time.sleep(1)
for i in range(3):
client.publish(f"{PREFIX}/test", f"hello {i}", qos=1)
time.sleep(1)
client.disconnect()
client.loop_stop()
Führen Sie es aus, und Sie sollten den Connect, die gewährte QoS, drei Publish-Bestätigungen und die drei Nachrichten sehen, die der öffentliche MQTT-Broker von ConnectMQ zurückliefert. Stellen Sie protocol auf mqtt.MQTTv311 um, und dieselben Callbacks funktionieren ohne Änderungen weiter – genau das verspricht VERSION2. Sind Sie neu bei der Bibliothek selbst, beginnen Sie zuerst mit dem Paho-MQTT-Python-Tutorial.
Fallstricke nach der Migration
Drittanbieter-Bibliotheken, die auf 1.x fixiert sind. Einige Pakete, die paho kapseln, haben paho-mqtt<2.0 in ihren Abhängigkeiten deklariert. Prüfen Sie das mit pip show und pip check. Aktuelle Releases der meisten gepflegten Wrapper unterstützen 2.x; aktualisieren Sie diese oder isolieren Sie Altwerkzeuge in einer eigenen virtuellen Umgebung.
Positionsargumente. Jeder Aufruf wie mqtt.Client("id", False, None, mqtt.MQTTv311) ist jetzt um eine Position verschoben. Wandeln Sie alle in Schlüsselwortargumente um; das macht künftige Upgrades schmerzlos.
Per Decorator registrierte Callbacks. Code, der @client.connect_callback() und ähnliche Decorators verwendet, muss die Signaturen der dekorierten Funktionen ebenfalls anpassen.
Verschluckte Exceptions. Standardmäßig protokolliert paho Exceptions, die in Callbacks ausgelöst werden, statt Ihr Programm abstürzen zu lassen. Eine falsche Signatur kann daher wie „nichts passiert" aussehen. Hängen Sie während der Migration mit client.enable_logger() einen Logger an, damit der TypeError sichtbar wird.
Reconnect-Logik. Haben Sie in on_disconnect Integer-Werte von rc verglichen, um über einen Reconnect zu entscheiden, schreiben Sie das auf reason_code um. Der Leitfaden zu Reconnects mit paho-mqtt zeigt robuste Muster, und der Leitfaden zu Python, MQTT und TLS behandelt die verschlüsselte Verbindung, die Sie in der Produktion verwenden sollten.
Sollten Sie stattdessen aiomqtt in Betracht ziehen?
Basiert Ihre Anwendung auf asyncio, kann die Migration der Callbacks ein guter Moment sein, ganz auf eine asynchrone API umzusteigen. aiomqtt kapselt paho und ersetzt Callbacks durch async for message in client.messages. Unser Tutorial zu aiomqtt und asyncio zeigt denselben Publish/Subscribe-Ablauf in dieser Form. Einen breiteren Vergleich von Python-Clients und Clients anderer Sprachen bietet die Übersicht über MQTT-Client-Bibliotheken.
Testen Sie Ihren migrierten Code auf ConnectMQ
ConnectMQ betreibt unter broker.connectmq.com einen kostenlosen öffentlichen MQTT-Broker, der sich ideal zur Überprüfung einer Migration eignet, sowie einen verwalteten MQTT-Broker für die Produktion mit MQTT 3.1.1 und 5.0, TLS auf 8883 und generierten Zugangsdaten. Das Portal enthält einen Live-Topic-Explorer, mit dem Sie bestätigen können, dass migrierte Clients weiterhin publizieren, was Sie erwarten. Sind Sie bereit, den öffentlichen Broker zu verlassen, betreiben Sie Ihre Clients auf einem privaten Cloud-MQTT-Broker: Registrieren Sie sich für den kostenlosen Serverless-Plan, ohne Kreditkarte.
Häufig gestellte Fragen
Was ist callback_api_version in paho-mqtt?
Es ist seit paho-mqtt 2.0 das erste Argument von mqtt.Client(). Es legt fest, welche Callback-Signaturen der Client verwendet: VERSION1 für den alten 1.x-Stil oder VERSION2 für den neuen, einheitlichen Stil.
Sollte ich VERSION1 oder VERSION2 verwenden?
Verwenden Sie VERSION2. VERSION1 existiert nur, damit alter Code weiterläuft, gibt eine Deprecation-Warnung aus und wird daher irgendwann entfernt.
Warum erhalte ich „Unsupported callback API version", wenn ich eine Client ID übergebe?
Sie haben die Client ID als erstes Positionsargument übergeben, das nun der Callback API Version vorbehalten ist. Übergeben Sie zuerst mqtt.CallbackAPIVersion.VERSION2 und die ID als client_id=....
Muss ich on_message bei der Migration ändern?
Nein. on_message(client, userdata, message) behält in beiden Versionen dieselbe Signatur. Die Änderungen betreffen die Callbacks für Connect, Disconnect, Subscribe, Unsubscribe und Publish.



