ZeroConf
ZeroConf is a pure Python implementation of multicast DNS service discovery (mDNS/DNS-SD), commonly known as Bonjour or Apple's Zero Configuration Networking. It allows applications to discover services on a local network without manual configuration. The library is currently at version 0.148.0 and maintains an active release cadence with frequent bug fixes and feature updates.
Warnings
- breaking The 1.0.0 release was unintentionally published due to an issue with `python-semantic-release` and was subsequently YANKED. It contained no breaking changes, but users should avoid attempting to install this specific version and instead rely on the latest 0.x.x releases.
- gotcha It is crucial to explicitly call the `close()` method on your `Zeroconf` instance(s) when you are done with them. Failing to do so will leave sockets open and consume resources, potentially leading to 'address already in use' errors or resource leaks.
- gotcha On systems with multiple network interfaces, `zeroconf` might not bind to the desired interface by default. If your service isn't discoverable or you're not seeing other services, explicitly specify the network interfaces to use during `Zeroconf` initialization.
Install
-
pip install zeroconf
Imports
- Zeroconf
from zeroconf import Zeroconf
- ServiceInfo
from zeroconf import ServiceInfo
- ServiceBrowser
from zeroconf import ServiceBrowser
- ServiceStateChange
from zeroconf import ServiceStateChange
Quickstart
import socket
import time
from zeroconf import ServiceInfo, Zeroconf, ServiceBrowser
# A simple listener for discovering services
class MyListener:
def add_service(self, zeroconf_instance, service_type, service_name):
info = zeroconf_instance.get_service_info(service_type, service_name)
if info:
print(f"Service added: {service_name} at {info.server}, Port: {info.port}, Addr: {socket.inet_ntoa(info.addresses[0]) if info.addresses else 'N/A'}")
def remove_service(self, zeroconf_instance, service_type, service_name):
print(f"Service removed: {service_name}")
# --- Example Usage ---
zeroconf = None
browser = None
info = None
try:
# 1. Register a service
desc = {'path': '/~example'}
ip_address = socket.gethostbyname(socket.gethostname()) # Or specify an explicit IP like "127.0.0.1"
info = ServiceInfo(
"_http._tcp.local.", # Service type
"MyTestService._http._tcp.local.", # Service name
addresses=[socket.inet_aton(ip_address)],
port=8080,
properties=desc,
server="example.local.", # The server's hostname
)
zeroconf = Zeroconf()
print(f"Registering service: {info.name} on {ip_address}:{info.port}")
zeroconf.register_service(info)
# 2. Browse for services (will also find our own registered service)
print("Starting service browser for _http._tcp.local.")
browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener=MyListener())
print("Running for 30 seconds to allow discovery and registration. Press Ctrl+C to stop.")
time.sleep(30) # Keep running
except KeyboardInterrupt:
print("Keyboard interrupt received. Shutting down.")
finally:
if zeroconf:
print("Unregistering service and closing Zeroconf...")
if info:
zeroconf.unregister_service(info)
zeroconf.close()
print("Cleanup complete.")