PyObjC Contacts Framework
PyObjC-framework-contacts provides Python bindings and wrappers for Apple's Contacts.framework on macOS. It allows Python developers to interact with the system's contact store, fetch, create, update, and delete contacts, and manage contact groups. The current version is 12.1, with a release cadence that generally follows macOS SDK updates and Python version support cycles.
Warnings
- breaking PyObjC 12.0 (and thus pyobjc-framework-contacts 12.x) dropped support for Python 3.9. Ensure your Python environment meets the `requires_python` specification.
- breaking PyObjC 11.1 introduced changes to align the core bridge's Automatic Reference Counting (ARC) behavior with `clang`'s documentation for initializer methods. Methods in the 'init' family now correctly steal a reference to self and return a new reference, which can affect custom memory management or subclassing patterns relying on the old behavior.
- gotcha In PyObjC 10.3, the ability to use `__init__` in custom Python subclasses was changed, particularly for classes relying on the `__new__` provided by PyObjC. While a fix in 10.3.1 restored `__init__` for user-implemented `__new__`, direct `__init__` calls on PyObjC-provided `__new__` are still restricted. This can affect how you initialize Python-defined subclasses of Cocoa objects.
- gotcha As of PyObjC 10.1, calling `os.fspath()` directly with Cocoa URL objects (`NSURL`, `CFURLRef`) that refer to local filesystem paths will work, but for other types of URLs, it will raise a `TypeError`. This ensures better integration with standard Python filesystem APIs but requires careful handling for non-local or generic URLs.
Install
-
pip install pyobjc-framework-contacts
Imports
- CNContactStore
from Contacts import CNContactStore
- CNContact
from Contacts import CNContact
- CNMutableContact
from Contacts import CNMutableContact
- NSArray
from Foundation import NSArray
Quickstart
from Contacts import CNContactStore, CNContactFetchRequest, CNContactGivenNameKey, CNContactFamilyNameKey
from Foundation import NSArray
def list_contact_names():
"""Fetches and prints the names of all contacts."""
store = CNContactStore.alloc().init()
# Define the keys (properties) to fetch for each contact
keys_to_fetch = [CNContactGivenNameKey, CNContactFamilyNameKey]
# CNContactFetchRequest expects an NSArray of keys
request = CNContactFetchRequest.alloc().initWithKeysToFetch_(NSArray.arrayWithArray_(keys_to_fetch))
contacts = []
# Enumerate contacts: the third argument is a Python callable (block)
# that gets called for each contact found.
success, error = store.enumerateContactsWithFetchRequest_error_(
request, None, lambda contact, stop: contacts.append(contact)
)
if not success:
print(f"Error fetching contacts: {error}")
return
if contacts:
print("Found contacts:")
for contact in contacts:
full_name = f"{contact.givenName() or ''} {contact.familyName() or ''}".strip()
if full_name:
print(f"- {full_name}")
else:
print(f"- (Unnamed contact, ID: {contact.identifier()})")
else:
print("No contacts found.")
if __name__ == '__main__':
# Note: Requires Contacts permission. First run might prompt for access.
list_contact_names()