{"id":5808,"library":"pyobjc-framework-fsevents","title":"PyObjC FSEvents Framework","description":"This library provides Python wrappers for the macOS FSEvents framework, allowing applications to monitor file system events efficiently. It is part of the larger PyObjC project, which bridges Python and the Objective-C runtime on macOS. The project follows macOS SDK updates closely, often releasing new versions with each major OS release, and is currently at version 12.1.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","framework","fsevents","pyobjc","filesystem","event-monitoring"],"install":[{"cmd":"pip install pyobjc-framework-fsevents","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Provides the core PyObjC bridge functionality required by all framework wrappers.","package":"pyobjc-core"}],"imports":[{"note":"Commonly used for creating a new FSEvents stream.","symbol":"FSEventStreamCreate","correct":"from FSEvents import FSEventStreamCreate"},{"note":"The core PyObjC bridge module, often needed for interacting with Objective-C types or methods.","symbol":"objc","correct":"import objc"}],"quickstart":{"code":"import objc\nfrom FSEvents import (\n    FSEventStreamCreate,\n    FSEventStreamScheduleWithRunLoop,\n    FSEventStreamStart,\n    FSEventStreamStop,\n    FSEventStreamRelease,\n    kFSEventStreamEventFlagNone,\n    kFSEventStreamEventFlagFileEvents,\n    kFSEventStreamCreateFlagUseCFTypes\n)\nfrom Foundation import CFRunLoopGetCurrent, CFRunLoopRunInMode, kCFRunLoopDefaultMode, CFRunLoopStop\n\ndef my_callback(streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIds):\n    print(f\"Detected {numEvents} events:\")\n    for i in range(numEvents):\n        path = eventPaths[i]\n        flags = eventFlags[i]\n        print(f\"  Path: {path}, Flags: {flags}\")\n\n\npath_to_monitor = \"./temp_monitor_dir\" # Change to a directory you want to monitor\nimport os\nif not os.path.exists(path_to_monitor):\n    os.makedirs(path_to_monitor)\n\n\ncb = objc.selector(my_callback, signature='v@iiii@*Q')\n\nstream = FSEventStreamCreate(\n    None, # allocator\n    cb, # callback\n    None, # context\n    [path_to_monitor], # pathsToWatch (array of CFStringRef)\n    0, # sinceWhen\n    1.0, # latency\n    kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamEventFlagFileEvents # flags\n)\n\nif stream is None:\n    print(\"Failed to create FSEventStream\")\nelse:\n    print(f\"Monitoring '{path_to_monitor}' for file system events. Press Ctrl+C to stop...\")\n    runLoop = CFRunLoopGetCurrent()\n    FSEventStreamScheduleWithRunLoop(stream, runLoop, kCFRunLoopDefaultMode)\n    FSEventStreamStart(stream)\n\n    try:\n        # Run the run loop for a short period, or forever for continuous monitoring\n        # For this example, we'll run for a fixed time or until stopped by user\n        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 30.0, False) # Run for 30 seconds\n    except KeyboardInterrupt:\n        print(\"\\nStopping monitoring...\")\n    finally:\n        FSEventStreamStop(stream)\n        FSEventStreamRelease(stream)\n        CFRunLoopStop(runLoop)\n        print(\"FSEventStream stopped and released.\")\n\n\n# Clean up the temporary directory if created by this script\n# if os.path.exists(path_to_monitor):\n#     os.rmdir(path_to_monitor)\n","lang":"python","description":"This quickstart demonstrates how to use `pyobjc-framework-fsevents` to monitor a specified directory for file system events. It sets up an `FSEventStream` with a Python callback function and schedules it on the current thread's `CFRunLoop`. It will monitor for 30 seconds or until a `KeyboardInterrupt` occurs. Remember that `pyobjc-framework-fsevents` is macOS-specific."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or newer, or pin your `pyobjc-framework-fsevents` dependency to `<12.0`.","message":"PyObjC 12.0 dropped support for Python 3.9. Ensure your project targets Python 3.10 or newer when upgrading to PyObjC 12.x.","severity":"breaking","affected_versions":"12.0+"},{"fix":"Upgrade your Python environment to 3.9 or newer (for PyObjC 11.x) or 3.10+ (for PyObjC 12.x), or pin `pyobjc-framework-fsevents` to `<11.0`.","message":"PyObjC 11.0 dropped support for Python 3.8. Projects using older Python versions need to upgrade before migrating to PyObjC 11.x.","severity":"breaking","affected_versions":"11.0+"},{"fix":"Review custom Objective-C class wrappers and memory management logic, especially around `init` methods, to ensure they correctly handle ARC semantics. Most Python-only code should be unaffected.","message":"PyObjC 11.1 aligned its behavior with `clang's documentation for automatic reference counting` for initializer methods. This means methods in the 'init' family now correctly steal a reference to self and return a new reference, which might change memory management expectations for custom Objective-C wrappers.","severity":"breaking","affected_versions":"11.1+"},{"fix":"Develop and deploy applications using PyObjC exclusively on macOS environments. Consider platform-agnostic alternatives if cross-platform compatibility is required.","message":"PyObjC and all `pyobjc-framework-*` packages are strictly macOS-only. Attempting to install or run them on other operating systems will fail.","severity":"gotcha","affected_versions":"All versions"},{"fix":"When subclassing Cocoa classes in Python, prefer to implement initialisation logic directly in the `__new__` method or by calling designated Objective-C initializers after object creation, rather than relying on Python's `__init__` for complex setup.","message":"In PyObjC 10.3, calling `__init__` on Python subclasses of Objective-C classes, specifically when a custom `__new__` method is present, could behave unexpectedly or be disabled. While 10.3.1 partially reintroduced support, using `__init__` with PyObjC's `__new__` for Objective-C class instantiation is generally discouraged.","severity":"gotcha","affected_versions":"10.3, 10.3.1+"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}