PyObjC Accessibility Framework
The `pyobjc-framework-accessibility` library provides Python wrappers for the macOS Accessibility framework, enabling programmatic interaction with user interface elements and assistive technologies. Currently at version 12.1, it is part of the broader PyObjC project, which typically releases updates in close synchronicity with new macOS versions and Python support cycles.
Warnings
- breaking PyObjC releases frequently drop support for older Python versions to align with CPython's end-of-life cycle. PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped Python 3.8. Always check the `requires_python` metadata for your target PyObjC version.
- gotcha Accessing macOS Accessibility features programmatically requires explicit user permission. The Python process running your script (e.g., Terminal, VS Code, or a standalone application) must be granted 'Accessibility' access in macOS System Settings > Privacy & Security > Accessibility. Without these permissions, most Accessibility API calls will fail or return `None`.
- gotcha From PyObjC 10.3 onwards, there were changes to how `__init__` and `__new__` interact when subclassing Objective-C classes. If you implement `__new__` in your Python subclass and *do not* explicitly call `super().__new__`, `__init__` may not be called, or its behavior may be unexpected. Version 10.3.1 partially re-enabled `__init__` for cases where user-defined `__new__` exists.
- gotcha Starting with PyObjC 11.1, the core bridge's behavior for 'init' family methods (initializers) aligns more strictly with `clang`'s Automatic Reference Counting (ARC) documentation. This means `init` methods now correctly model stealing a reference to `self` and returning a new reference. Code relying on previous PyObjC memory management assumptions for initializers may need adjustment.
Install
-
pip install pyobjc-framework-accessibility
Imports
- Accessibility
import Accessibility
- AXUIElementCreateSystemWide
from Accessibility import AXUIElementCreateSystemWide
Quickstart
import Accessibility
import AppKit
# IMPORTANT: This code requires granting accessibility permissions to the
# Python process (e.g., Terminal.app or your IDE) in macOS System Settings >
# Privacy & Security > Accessibility. Without permissions, most Accessibility
# functions will fail or return None.
def get_accessibility_info():
# Get the system-wide accessibility element
system_wide_element = Accessibility.AXUIElementCreateSystemWide()
if not system_wide_element:
print("Could not create system-wide accessibility element. Check permissions.")
return
print(f"System-wide element description: {system_wide_element.description()}")
# Get the currently focused application
workspace = AppKit.NSWorkspace.sharedWorkspace()
frontmost_app = workspace.frontmostApplication()
if frontmost_app:
app_name = frontmost_app.localizedName()
app_pid = frontmost_app.processIdentifier()
print(f"\nFrontmost Application: {app_name} (PID: {app_pid})")
# Create an accessibility element for the frontmost application
app_ax_element = Accessibility.AXUIElementCreateApplication(app_pid)
if app_ax_element:
try:
# Attempt to get common attributes
role = app_ax_element.attributeForKey_(Accessibility.kAXRoleAttribute)
title = app_ax_element.attributeForKey_(Accessibility.kAXTitleAttribute)
print(f" Role: {role if role else 'N/A'}")
print(f" Title: {title if title else 'N/A'}")
except Exception as e:
print(f" Error accessing app attributes (permissions?): {e}")
else:
print(f" Could not create AXUIElement for {app_name}.")
else:
print("No frontmost application found.")
# Call the function, ensuring it's wrapped to explain permissions
print("Attempting to get Accessibility information...")
get_accessibility_info()
print("\nRemember to grant Accessibility permissions to your Python environment in macOS System Settings > Privacy & Security > Accessibility.")