async-upnp-client

raw JSON →
0.47.0 verified Mon Apr 27 auth: no python

Async UPnP Client library for Python, implementing UPnP (Universal Plug and Play) protocol asynchronously using asyncio. Current version 0.47.0, release cadence is irregular, roughly monthly. Requires Python >=3.10.

pip install async-upnp-client
error ModuleNotFoundError: No module named 'async_upnp_client'
cause Library not installed.
fix
Run pip install async-upnp-client.
error ImportError: cannot import name 'UPnPDevice' from 'async_upnp_client'
cause Incorrect import path in older versions?
fix
Use from async_upnp_client import UPnPDevice directly.
error RuntimeError: Task <Task pending> got Future <Future pending> attached to a different loop
cause Mixing asyncio event loops, often due to using asyncio.run() inside an already running loop.
fix
Ensure single event loop usage; avoid nesting asyncio.run().
breaking Version 0.47.0 removed deprecated classmethods from UPnPDevice and UPnPService. Use factory pattern instead.
fix Use UPnPFactory.create_device() and UPnPService.from_device() instead of classmethods.
gotcha The library uses async/await exclusively. Mixing synchronous code will cause RuntimeError or deadlocks.
fix Ensure all calls to async methods are awaited within an async context.
deprecated UPnPRequester is deprecated in favor of aiohttp session-based approach. Future versions may remove it.
fix Use aiohttp.ClientSession directly and pass to factory.
gotcha UPnP device discovery using SSDP may require root privileges on some systems (e.g., Linux) due to port binding.
fix Run the script as root or use `sudo` for discovery. Alternatively, hardcode device URL.

Basic setup to instantiate a UPnP factory and requester.

import asyncio
from async_upnp_client import UPnPFactory, UPnPRequester

async def main():
    requester = UPnPRequester()
    factory = UPnPFactory(requester)
    # Discover devices, for example:
    # device = await factory.create_device("http://192.168.1.1:49152/description.xml")
    print("UPnP client ready")

asyncio.run(main())