launchd is a pythonic interface to interact with macOS's launchd. It provides access to basic querying and interaction with launchd. It is implemented using the Objective C ServiceManagement framework as well as the launchd command line utility. Therefore, this python package can only be used on macOS
The relevant import statement is:
import launchdListing all launchd jobs:
for job in launchd.jobs():
print(job.label, job.pid, job.properties, job.plistfilename)Find the pid of a job:
>>> launchd.LaunchdJob("com.apple.Finder").pid
278
>>> launchd.LaunchdJob("com.example.fubar").pid
Traceback (most recent call last):
File "launchd/launchctl.py", line 78, in refresh
raise ValueError("job '%s' does not exist" % self.label)
ValueError: job 'com.example.fubar' does not existDetect if a job exists:
>>> launchd.LaunchdJob("com.example.fubar").exists()
Falselaunchd job properties (these come directly from launchd and NOT the .plist files):
>>> launchd.LaunchdJob("com.apple.Finder").properties
{'Label': 'com.apple.Finder', 'PlistPath': '/System/Library/LaunchAgents/com.apple.Finder.plist', 'Scope': 4, 'Status': 'unknown', 'StatusCode': None, 'Registered': True}
>>> launchd.LaunchdJob("com.apple.Finder").properties["Label"]
'com.apple.Finder'Find all plist filenames of currently running jobs:
for job in launchd.jobs():
if job.pid is None or job.plistfilename is None:
continue
print(job.plistfilename)Job properties of a given job (this uses the actual .plist file):
>>> launchd.plist.read("com.apple.Finder")
{'POSIXSpawnType': 'App', 'RunAtLoad': False, 'KeepAlive': {'SuccessfulExit': False, 'AfterInitialDemand': True}, 'Label': 'com.apple.Finder', 'Program': '/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder', 'CFBundleIdentifier': 'com.apple.finder', 'ThrottleInterval': 1}$ pip install launchdor, if you prefer working from a local checkout:
$ python -m build
$ pip install dist/launchd-*.whl- OS X >= 10.6
- Python 3.10+
- macOS 13+ for the SMAppService-backed job metadata API
Job metadata is now collected through Apple’s SMAppService API. Because that interface only exposes helper plists that the calling bundle can manage, launchd.jobs() now reports the property lists SMAppService can inspect (status, bundled configuration, etc.). pid/LastExitStatus therefore remain None in most cases, but properties["Config"] still contains the original plist contents. The low-level launchctl binary remains the implementation for load()/unload() until Apple publishes a direct replacement.
Run the unit tests (example uses Python 3.10):
$ tox -e py310Verify style/lint checks:
$ tox -e styleBuild the source distribution and wheel:
$ python -m buildPublish via Twine (this rebuilds as part of the command):
$ tox -e release