【问题标题】:How to get active window title using Python in Mac?如何在 Mac 中使用 Python 获取活动窗口标题?
【发布时间】:2015-05-03 03:55:09
【问题描述】:

我正在尝试编写 Python 脚本,该脚本在 Mac OS 中使用 python 打印活动窗口的标题。

这是我的代码:

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

此代码仅打印应用程序的名称,例如 Google chrome 或 firefox,而不是标题。如何获取窗口的标题?

【问题讨论】:

标签: python macos


【解决方案1】:

这是我过去使用 Python 使用 Quartz API 在 Mac OS X 上查找活动应用程序名称和窗口标题的内容。

首先,我们需要根据需要添加导入:

if sys.platform == "darwin":
    import applescript
    from AppKit import NSWorkspace
    from Quartz import (
        CGWindowListCopyWindowInfo,
        kCGWindowListOptionOnScreenOnly,
        kCGNullWindowID
    )

然后我们就可以通过下面的代码获取活动应用名称和窗口标题:

def getActiveInfo(event_window_num):
    try:
        if sys.platform == "darwin":
            app = NSWorkspace.sharedWorkspace().frontmostApplication()
            active_app_name = app.localizedName()

            options = kCGWindowListOptionOnScreenOnly
            windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)
            windowTitle = 'Unknown'
            for window in windowList:
                windowNumber = window['kCGWindowNumber']
                ownerName = window['kCGWindowOwnerName']
                # geometry = window['kCGWindowBounds']
                windowTitle = window.get('kCGWindowName', u'Unknown')
                if windowTitle and (
                                event_window_num == windowNumber
                        or ownerName == active_app_name
                ):
                    # log.debug(
                    #     'ownerName=%s, windowName=%s, x=%s, y=%s, '
                    #     'width=%s, height=%s'
                    #     % (window['kCGWindowOwnerName'],
                    #        window.get('kCGWindowName', u'Unknown'),
                    #        geometry['X'],
                    #        geometry['Y'],
                    #        geometry['Width'],
                    #        geometry['Height']))
                    break

            return _review_active_info(active_app_name, windowTitle)
        if sys.platform == "win32":
            (active_app_name, windowTitle) = _getActiveInfo_Win32()
            return _review_active_info(active_app_name, windowTitle)
    except:
        log.error('Unexpected error: %s' % sys.exc_info()[0])
        log.error('error line number: %s' % sys.exc_traceback.tb_lineno)
    return 'Unknown', 'Unknown'

【讨论】:

  • 你能给出一个完整的shell例子吗?我不明白 event_window_num 参数的用途。或 _review_active_info()。
  • @Yehosef event_window_num 是从鼠标事件或键盘事件中捕获的,我想你可以放心地忽略这个参数。 _review_active_info 也是我的应用中的一个自定义函数,只是验证我们得到的 app_name 和 window_title,你也可以忽略这个方法。获取活动app_name和window_title的核心部分如示例代码所示。
  • 不幸的是,我马上就收到了一个错误 import applescript : ImportError: No module named applescript
【解决方案2】:

NSWorkspace.sharedWorkspace().activeApplication() 无法访问应用标题。

但是你可以通过它的PID找到当前窗口的标题:

例如:

from AppKit import NSWorkspace
pid = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationProcessIdentifier']

然后使用下面的代码找到正确的窗口(它存储在kCGWindowOwnerPID中)如下代码所示:

这是一个基于@JakeW's script的完整shell示例:

#!/usr/bin/python
# Prints list of windows in the current workspace.
import sys
if sys.platform == "darwin":
    from AppKit import NSWorkspace
    from Quartz import (
        CGWindowListCopyWindowInfo,
        kCGWindowListOptionOnScreenOnly,
        kCGNullWindowID
    )

if sys.platform == "darwin":
    curr_app = NSWorkspace.sharedWorkspace().frontmostApplication()
    curr_pid = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationProcessIdentifier']
    curr_app_name = curr_app.localizedName()
    options = kCGWindowListOptionOnScreenOnly
    windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)
    for window in windowList:
        pid = window['kCGWindowOwnerPID']
        windowNumber = window['kCGWindowNumber']
        ownerName = window['kCGWindowOwnerName']
        geometry = window['kCGWindowBounds']
        windowTitle = window.get('kCGWindowName', u'Unknown')
        if curr_pid == pid:
            print("%s - %s (PID: %d, WID: %d): %s" % (ownerName, windowTitle.encode('ascii','ignore'), pid, windowNumber, geometry))
elif sys.platform == "win32":
    (active_app_name, windowTitle) = _getActiveInfo_Win32()

它将列出当前活动窗口的详细信息,包括其标题。

【讨论】:

  • 这会列出活动应用程序的所有窗口,而不仅仅是活动窗口。例如。在 chrome 中在单独的窗口中打开开发者工具,您无法区分哪个是活动的。
  • 你需要在curr_pid == pid:之后添加一个break,并且还要检查windowTitle是否存在
  • 这有效,Jake W 投票较高的答案无效。
【解决方案3】:

从 macOS 10.6 及更高版本开始,最好使用:frontmostApplication,如果您想获取所有列出的应用程序,可以调用 runningApplications 方法。

您可以在https://developer.apple.com/documentation/appkit/nsworkspace#overview查看更多详细信息

例如:

from AppKit import NSWorkspace
NSWorkspace.sharedWorkspace().runningApplications() // for getting all applications
NSWorkspace.sharedWorkspace().frontmostApplication() // for active window

【讨论】:

  • 这个答案写得很好,但没有解决OP关于窗口标题的问题。你能用如何获得这个标题更新你的答案吗?
猜你喜欢
  • 2012-02-25
  • 1970-01-01
  • 2013-02-06
  • 2012-05-03
  • 2010-10-03
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多