Как управлять macOS с помощью Python?

5 лучших веб-фреймворков Python 2022 года Изучение

В этом кратком совете, взятом из книги «Useful Python».

Работая на Mac, мы можем контролировать почти все в системе, используя pyobjc, мост Python-to-Objective-C. Apple делает большую часть своей ОС управляемой через модуль AppKit и pyobjcпредоставляет доступ ко всему этому Python. Это будет наиболее полезно, если мы уже знаем, как AppKit делает то, что мы хотим, но с небольшим исследованием можно пробиться через API-интерфейсы операционной системы.

Давайте попробуем пример. Во-первых, нам понадобится pyobjc, который можно установить с помощью pip install pyobjc. Это установит целый список мостов API операционной системы, предоставляя доступ ко всем видам аспектов macOS. Сейчас мы рассмотрим AppKit — инструмент, используемый для создания и управления запущенными приложениями на рабочем столе Mac.

Мы можем перечислить все приложения, запущенные в настоящее время с помощью AppKit:

Python 3.9.6 (default, Oct 18 2022, 12:41:40) 
[Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from AppKit import NSWorkspace
>>> NSWorkspace.sharedWorkspace().runningApplications() 
(
    "<NSRunningApplication: 0x60000145c000 (com.apple.loginwindow - 148) LSASN:{hi=0x0;lo=0x6006}>",
    "<NSRunningApplication: 0x60000145c080 (com.apple.backgroundtaskmanagement.agent - 475) LSASN:{hi=0x0;lo=0xb00b}>",
    "<NSRunningApplication: 0x60000145c100 (com.apple.WindowManager - 474) LSASN:{hi=0x0;lo=0xc00c}>",
    "<NSRunningApplication: 0x60000145c180 (com.apple.CoreLocationAgent - 500) LSASN:{hi=0x0;lo=0xe00e}>",
    "<NSRunningApplication: 0x60000145c980 (com.apple.Terminal - 1302) LSASN:{hi=0x0;lo=0x24024}>",
    "<NSRunningApplication: 0x60000145ca00 (com.apple.Safari - 1303) LSASN:{hi=0x0;lo=0x25025}>",
    "<NSRunningApplication: 0x60000145cb80 (com.apple.Spotlight - 1310) LSASN:{hi=0x0;lo=0x28028}>",
    "<NSRunningApplication: 0x60000145cc00 (com.apple.finder - 1306) LSASN:{hi=0x0;lo=0x29029}>",
)
>>> 

Это даст длинный список NSRunningApplicationобъектов. Каждый из них соответствует определенному приложению, работающему в данный момент на рабочем столе. Многие из них являются «невидимыми» приложениями (вещи, которые работают, но не обязательно показывают окно), но есть и такие вещи, которые мы могли бы считать реальными приложениями, которые мы можем видеть, например Safari, Terminal и т. д. NSRunningApplicationзадокументирован на сайте developer.apple.com, где можно увидеть его свойства. Например, у каждого приложения есть localizedNameи 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
Spotlight -> com.apple.Spotlight
Finder -> com.apple.finder

Мы также можем видеть, что у NSRunningApplicationобъекта есть функция активации, которую мы можем вызвать, чтобы активировать это приложение, как если бы мы щелкнули его значок в Dock. Итак, чтобы найти Safari, а затем активировать его, мы будем использовать эту функцию активации. Для вызова activateтребуется значение для options, как описано в документации, и его также необходимо импортировать из 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)

Теперь Safari активирован.

Читайте также:  Компьютерная сеть за 5 минут: статический IP-адрес против динамического IP-адреса

Поиск версий Python для API macOS

Найти имя чего-то в Python, которое соответствует имени Objective-C, может быть немного сложно. Как показано в приведенном выше коде, activateфункция Objective-C вызывается activateWithOptions_в Python. Существует набор правил для перевода этого имени, который объясняется в документации pyobjc, но иногда может быть быстрее использовать собственную функцию Python, dir()чтобы показать все свойства объекта, а затем выбрать то, которое выглядит наиболее правдоподобно:

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

Ой! Наш safariэкземпляр NSRunningApplicationимеет 452 свойства! Ну, тот, который нам нужен, вероятно, называется что-то вроде «активировать», поэтому:

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

Ага! Так же activateWithOptions_как и имя функции, которую нам нужно вызвать. Точно так же имя опции, которую мы хотим передать этой функции, находится в самом AppKit:

>>> [x for x in dir(AppKit) if "ignoringotherapps" in x.lower()]
['NSApplicationActivateIgnoringOtherApps']

Иногда этот процесс может показаться немного исследовательским, но все, что Objective-C может сделать, можно сделать и из Python.

Оцените статью
bestprogrammer.ru
Добавить комментарий