{"library":"pymodbus","title":"Pymodbus","description":"Pymodbus is a fully featured Modbus protocol stack implemented in Python, offering client and server capabilities for TCP, UDP, and serial communication. It primarily leverages `asyncio` for modern asynchronous operations and is actively maintained with frequent minor releases focusing on bug fixes and incremental improvements. The current version is 3.12.1.","language":"python","status":"active","last_verified":"Fri May 15","install":{"commands":["pip install pymodbus"],"cli":null},"imports":["from pymodbus.client import ModbusTcpClient","from pymodbus.server import StartAsyncTcpServer","from pymodbus.datastore import ModbusSlaveContext, ModbusSequentialDataBlock"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import asyncio\nimport logging\nfrom pymodbus.client import ModbusTcpClient\nfrom pymodbus.server import StartAsyncTcpServer\nfrom pymodbus.datastore import ModbusSlaveContext, ModbusSequentialDataBlock\n\nlogging.basicConfig(level=logging.INFO)\nlog = logging.getLogger(__name__)\n\nasync def run_modbus_server():\n    # Setup a simple Modbus datastore for Slave ID 1\n    store = ModbusSlaveContext(\n        di=ModbusSequentialDataBlock(0, [17]*10),\n        co=ModbusSequentialDataBlock(0, [17]*10),\n        hr=ModbusSequentialDataBlock(0, [17]*10),\n        ir=ModbusSequentialDataBlock(0, [17]*10)\n    )\n    context = ModbusSlaveContext(slaves={0x01: store}, single=False)\n\n    server_task = StartAsyncTcpServer(\n        context=context,\n        address=(\"localhost\", 5020),\n        allow_reuse_address=True\n    )\n    log.info(\"Modbus TCP Server starting on localhost:5020\")\n    await server_task # This will block until cancelled\n\nasync def run_modbus_client():\n    await asyncio.sleep(1) # Give server a moment to start\n    log.info(\"Modbus TCP Client connecting to localhost:5020\")\n    client = ModbusTcpClient(\"localhost\", 5020)\n    if await client.connect():\n        log.info(\"Client connected successfully.\")\n        \n        # Read holding registers (address 0, count 5, slave ID 1)\n        result = await client.read_holding_registers(address=0, count=5, slave=1)\n        if result.is_success():\n            log.info(f\"Read holding registers: {result.registers}\")\n        else:\n            log.error(f\"Failed to read holding registers: {result}\")\n\n        # Write to holding registers (address 0, values [99, 98, 97], slave ID 1)\n        write_result = await client.write_registers(address=0, values=[99, 98, 97], slave=1)\n        if write_result.is_success():\n            log.info(f\"Wrote to holding registers.\")\n        else:\n            log.error(f\"Failed to write holding registers: {write_result}\")\n\n        # Read again to verify write\n        result_after_write = await client.read_holding_registers(address=0, count=5, slave=1)\n        if result_after_write.is_success():\n            log.info(f\"Read holding registers after write: {result_after_write.registers}\")\n        else:\n            log.error(f\"Failed to read holding registers after write: {result_after_write}\")\n\n        client.close()\n        log.info(\"Client disconnected.\")\n    else:\n        log.error(\"Client failed to connect.\")\n\nasync def main():\n    server_task = asyncio.create_task(run_modbus_server())\n    try:\n        await run_modbus_client()\n    finally:\n        server_task.cancel() # Signal server to shut down\n        try:\n            await server_task\n        except asyncio.CancelledError:\n            log.info(\"Server task cancelled successfully.\")\n        except Exception as e:\n            log.error(f\"Server task ended with unexpected error: {e}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())","lang":"python","description":"This quickstart demonstrates a basic asynchronous Modbus TCP server and client. The server runs on localhost:5020, serving a simple datastore. The client connects, reads initial holding registers, writes new values, and then reads again to verify the write operation, before gracefully shutting down the server.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-15","installed_version":"3.8.6","pypi_latest":"3.13.0","is_stale":true,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":1.6,"avg_import_s":0.31,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.17,"mem_mb":5.3,"disk_size":"18.9M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.6,"import_time_s":0.13,"mem_mb":5.3,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.25,"mem_mb":6.6,"disk_size":"20.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.23,"mem_mb":6.6,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.51,"mem_mb":9,"disk_size":"12.8M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.48,"mem_mb":9,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.53,"mem_mb":9.5,"disk_size":"12.5M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.47,"mem_mb":9.5,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.15,"mem_mb":7.1,"disk_size":"18.4M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pymodbus","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.9,"import_time_s":0.14,"mem_mb":7.1,"disk_size":"19M"}]}}