{"library":"psygnal","title":"psygnal","description":"Psygnal is a pure Python implementation of the observer pattern, providing a fast callback and event system modeled after Qt Signals & Slots. It offers optional signature and type checking for connected slots and supports threading, all without requiring or using Qt. The current version is 0.15.1, and the library is actively maintained with regular releases.","language":"python","status":"active","last_verified":"Thu May 14","install":{"commands":["pip install psygnal"],"cli":null},"imports":["from psygnal import Signal","from psygnal import evented","from psygnal.containers import EventedList","from psygnal import EventedModel","from psygnal import debounced","from psygnal import throttled"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"from psygnal import Signal\n\nclass MyObject:\n    \"\"\"A simple object that emits a signal when its value changes.\"\"\"\n    value_changed = Signal(str)\n\n    def __init__(self, initial_value: str = \"\"):\n        self._value = initial_value\n\n    def set_value(self, new_value: str):\n        if new_value != self._value:\n            self._value = new_value\n            self.value_changed.emit(self._value)\n\n# Create an instance of the object\nmy_obj = MyObject(\"start\")\n\n# Connect a callback function using the .connect() method\ndef on_value_change_method(new_value: str):\n    print(f\"Callback 1 (method): The value changed to '{new_value}'!\")\n\nmy_obj.value_changed.connect(on_value_change_method)\n\n# Connect another callback function using the @.connect decorator\n@my_obj.value_changed.connect\ndef on_value_change_decorator(new_value: str):\n    print(f\"Callback 2 (decorator): I also received: '{new_value}'!\")\n\nprint(\"Initial value set, no emission yet.\")\n\n# Emit signals by changing the value\nprint(\"\\nSetting value to 'hello':\")\nmy_obj.set_value(\"hello\")\n\nprint(\"\\nSetting value to 'world':\")\nmy_obj.set_value(\"world\")\n\nprint(\"\\nSetting value to 'world' again (should not emit):\")\nmy_obj.set_value(\"world\")\n\n# Disconnect a callback\nmy_obj.value_changed.disconnect(on_value_change_method)\nprint(\"\\nDisconnected 'Callback 1'. Setting value to 'psygnal':\")\nmy_obj.set_value(\"psygnal\")","lang":"python","description":"This example demonstrates how to define a signal, connect multiple callbacks (both directly and with a decorator), emit a signal, and disconnect a callback. Note that a signal is only emitted if the value truly changes.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-14","installed_version":"0.14.2","pypi_latest":"0.15.1","is_stale":true,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":1.7,"avg_import_s":0.14,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.12,"mem_mb":4.6,"disk_size":"20.7M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":4.6,"disk_size":"20.7M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.09,"mem_mb":4.6,"disk_size":"21M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":4.6,"disk_size":"21M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"psygnal","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.5,"disk_size":"22.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":5.5,"disk_size":"22.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.15,"mem_mb":5.5,"disk_size":"23M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":5.5,"disk_size":"23M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.15,"mem_mb":5.3,"disk_size":"14.7M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":5.3,"disk_size":"14.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.15,"mem_mb":5.3,"disk_size":"15M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":5.3,"disk_size":"15M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.15,"mem_mb":5.4,"disk_size":"14.4M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":5.4,"disk_size":"14.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.14,"mem_mb":5.4,"disk_size":"15M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":5.4,"disk_size":"15M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.1,"mem_mb":4.4,"disk_size":"20.2M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":4.4,"disk_size":"20.2M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.9,"import_time_s":0.09,"mem_mb":4.4,"disk_size":"21M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"psygnal","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":4.4,"disk_size":"21M"}]}}