on this fast tip, excerpted from useful python, stuart seems to be at methods to manage the home windows os with python.

engaged on a mac, we will management nearly every part concerning the system utilizing pyobjc, the python-to-goal-c bridge. apple makes most of its os controllable through the appkit module, and pyobjc provides python entry to all of this. this can be most helpful if we already know the appkit method to do the factor we wish, however with just a little exploration it’s doable to make our means via the working system apis.

let’s strive an instance. first, we’ll want pyobjc, which will be put in with pip set up pyobjc. this may set up a complete record of working system api bridges, permitting entry to all kinds of facets of macos. for now, we’ll think about appkit, which is the instrument used to construct and management operating apps on a mac desktop.

we will record all of the functions at present operating utilizing appkit:

python 3.9.6 (default, oct 18 2022, 12:41:40) 
[clang 14.0.0 (clang-1400.0.29.202)] on darwin
sort "assist", "copyright", "credit" or "license" for extra data.
>>> from appkit import nsworkspace
>>> nsworkspace.sharedworkspace().runningapplications() 
(
    "<nsrunningapplication: 0x60000145c000 (com.apple.loginwindow - 148) lsasn:{hello=0x0;lo=0x6006}>",
    "<nsrunningapplication: 0x60000145c080 (com.apple.backgroundtaskmanagement.agent - 475) lsasn:{hello=0x0;lo=0xb00b}>",
    "<nsrunningapplication: 0x60000145c100 (com.apple.windowmanager - 474) lsasn:{hello=0x0;lo=0xc00c}>",
    "<nsrunningapplication: 0x60000145c180 (com.apple.corelocationagent - 500) lsasn:{hello=0x0;lo=0xe00e}>",
    "<nsrunningapplication: 0x60000145c980 (com.apple.terminal - 1302) lsasn:{hello=0x0;lo=0x24024}>",
    "<nsrunningapplication: 0x60000145ca00 (com.apple.safari - 1303) lsasn:{hello=0x0;lo=0x25025}>",
    "<nsrunningapplication: 0x60000145cb80 (com.apple.highlight - 1310) lsasn:{hello=0x0;lo=0x28028}>",
    "<nsrunningapplication: 0x60000145cc00 (com.apple.finder - 1306) lsasn:{hello=0x0;lo=0x29029}>",
)
>>> 

this may give an extended record of nsrunningapplication objects. each corresponds to a particular software at present operating on the desktop. many are “invisible” functions (issues which are operating however aren’t essentially exhibiting a window), however others are issues that we’d consider as precise functions that we will see—corresponding to safari, terminal, and so forth. nsrunningapplication is documented at developer.apple.com, the place its properties will be seen. for instance, every software has a localizedname and a bundleidentifier:

>>> for nsapp in nsworkspace.sharedworkspace().runningapplications():
...   print(f"{nsapp.localizedname()} -> {nsapp.bundleidentifier()}")
... 
loginwindow -> com.apple.loginwindow
backgroundtaskmanagementagent -> com.apple.backgroundtaskmanagement.agent
windowmanager -> com.apple.windowmanager
corelocationagent -> com.apple.corelocationagent
terminal -> com.apple.terminal
safari -> com.apple.safari
highlight -> com.apple.highlight
finder -> com.apple.finder

we will additionally see {that a} nsrunningapplication object has an activate perform, which we will name to activate that app as if we had clicked its icon within the dock. so, to search out safari after which activate it, we might use that activate perform. the decision to activate requires a price for choices, because the documentation describes, and that additionally must be imported from appkit:

>>> from appkit import nsworkspace, nsapplicationactivateignoringotherapps
>>> safari_list = [x for x in nsworkspace.sharedworkspace().runningapplications()
    if x.bundleidentifier() == 'com.apple.safari']
>>> safari = safari_list[0]
>>> safari.activatewithoptions_(nsapplicationactivateignoringotherapps)

now safari is activated.

discovering python variations of macos apis

discovering the title of one thing in python that corresponds to the goal-c title generally is a little difficult. as proven within the code above, the goal-c activate perform is named activatewithoptions_ in python. there’s a algorithm for this title translation, which the pyobjc documentation explains, however it will probably generally be faster to make use of python’s personal dir() perform to indicate all of the properties of an object after which pick the one that appears most believable:

>>> print(len(dir(safari)))
452

ouch! our safari occasion of an nsrunningapplication has 452 properties! effectively, the one we wish might be referred to as one thing like “activate”, so:

>>> print([x for x in dir(safari) if "activate" in x.lower()])
['activatewithoptions_', 'activatewithoptions_']

aha! so activatewithoptions_ is the title of the perform we have to name. equally, the title of the choice we need to go to that perform is in appkit itself:

>>> [x for x in dir(appkit) if "ignoringotherapps" in x.lower()]
['nsapplicationactivateignoringotherapps']

this course of can really feel just a little exploratory at instances, nevertheless it’s doable to do something that goal-c can do from python as properly.

this text is excerpted from useful python, accessible on Pylogix premium and from book retailers.