Поиск текущего активного окна в Mac OS X с помощью Python

Есть ли способ найти имя приложения текущего активного окна в определенный момент времени в Mac OS X с помощью Python?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
22
0
19 891
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Во-первых, вам нужно окно или название приложения? Это не Windows - процесс приложения в Mac OS X может иметь несколько окон. (Более того, уже несколько лет это относится и к Windows, хотя я понятия не имею, как выглядит API для этого.)

Во-вторых, углерод или какао?

Чтобы получить активное окно в Какао:

window = NSApp.mainWindow()

Чтобы получить имя вашего процесса в Какао:

appName = NSProcessInfo.processInfo().processName()

Редактировать: О, думаю, я знаю, чего вы хотите. Название самого переднего процесса, верно?

Я не думаю, что есть способ сделать это в Cocoa, но вот как это сделать в Carbon на C:

ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/

CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/

Не забудьте о CFRelease(processName), когда закончите с ним.

Я не уверен, как это будет выглядеть в Python и возможно ли это вообще. В Python нет указателей, что усложняет задачу.

Я знаю, что PyObjC переведет последний аргумент CopyProcessName в err, processName = CopyProcessName(…), но привязки Carbon не полагаются на PyObjC (они являются частью ядра Python 2), и я не уверен, что вы делаете с PSN в любом случае.

Что нам нужно импортировать, чтобы получить NSApp и NSProcessInto?

GreenAsJade 27.01.2014 01:59

@GreenAsJade: Исходя из ответа Дирка, предположительно Foundation и AppKit.

Peter Hosey 27.01.2014 02:34

Поскольку исходный вопрос касался Python, обратите внимание, что CFRelease не требуется с PyObjC. PyObjC обрабатывает это за вас, AFAIK.

Dale 01.07.2019 00:07
Ответ принят как подходящий

Это должно работать:

#!/usr/bin/python

from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName

Работает только на Leopard или на Tiger, если у вас установлен PyObjC и случайно указывает на правильный двоичный файл python в первой строке (не тот случай, если вы установили универсальный MacPython, что вы, вероятно, захотите сделать на Tiger). Но ответ Питера с углеродным способом сделать это, вероятно, будет немного быстрее, поскольку импорт чего-либо из AppKit в Python занимает некоторое время, а точнее, импорт чего-либо из AppKit в первый раз в процессе Python занимает некоторое время.

Если вам это нужно внутри приложения PyObjC, то, что я описываю, будет работать отлично и быстро, поскольку вы испытываете задержку при импорте AppKit только один раз. Если вам нужно, чтобы это работало как инструмент командной строки, вы заметите снижение производительности. Если это актуально для вас, вам, вероятно, лучше создать 10-строчный инструмент командной строки Foundation в Xcode, используя код Питера в качестве отправной точки.

Мне нужно было текущее самое переднее приложение в скрипте Python, который красиво размещает окна на моем экране (см. move_window).

Конечно, вся заслуга Питера! Но вот полная программа:

#include <Carbon/Carbon.h>

int main(int, char) {
    ProcessSerialNumber psn = { 0L, 0L };
    OSStatus err = GetFrontProcess(&psn);

    CFStringRef processName = NULL;
    err = CopyProcessName(&psn, &processName);
    printf("%s\n", CFStringGetCStringPtr(processName, NULL));
    CFRelease(processName);
}

Сборка с gcc -framework Carbon filename.c

Как это ответ для Python?

GreenAsJade 27.01.2014 01:56

Также не для Python, но для новой автоматизации Yosemite JavaScript вы можете использовать $.NSWorkspace.sharedWorkspace.activeApplication.objectForKey‌​('NSApplicationName'‌​).UTF8String;. Однако сначала вам нужно импортировать это: ObjC.import('AppKit').

SirVer 15.02.2015 11:49

На данный момент CopyProcessName явно помечено как устаревшее.

Isilmë O. 19.04.2018 20:42

Метод в принятом ответе устарел в OS X 10.7+. Текущая рекомендуемая версия будет следующей:

from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)

Это действительно помогает! Как мы можем получить заголовок активного окна?

Jake W 16.01.2015 10:10

Я знаю, что это можно сделать с помощью AppleScript (вызывая его через osascript в Python), но, насколько мне известно, на Python нет простого способа сделать это. Вот ссылка для проверки информации, которую вы можете получить с помощью Какао: developer.apple.com/library/mac/documentation/Cocoa/Referenc‌ e /…

kmundnic 17.01.2015 16:49

Первоначально мы использовали AppleScript для получения текущего заголовка окна, что отлично работало. Но это не сработало, если мы подписали приложение. А затем я нашел собственный API в Quartz для этого, и это решило нашу проблему.

Jake W 18.01.2015 04:48

По какой-то причине это всегда давало мне имя моего терминала. В принятом ответе все было правильно. Я использую OS X 10.10.

erb 05.03.2015 12:44

@JakeW - не могли бы вы рассказать, как вам это удалось? что за API?

Yehosef 20.05.2016 03:31

@Yehosef Я добавил новый ответ, чтобы он мог отображать образец кода в лучшем формате. Надеюсь, это будет вам полезно.

Jake W 20.05.2016 05:23

@JakeW - спасибо! Но где ответ? Я этого не вижу.

Yehosef 22.05.2016 01:35

@Yehosef По мнению обозревателей, я добавил ответ на этот вопрос: stackoverflow.com/questions/28815863/…, что более актуально. В основном способ получения имени приложения такой же, нативная часть, которую я нашел, предназначена для получения заголовка окна с помощью Quartz.

Jake W 22.05.2016 01:58

Другие вопросы по теме