【问题标题】:Getting the active application on OS X 10.7 using a python daemon使用 python 守护程序在 OS X 10.7 上获取活动应用程序
【发布时间】:2012-02-29 22:55:04
【问题描述】:

我正在尝试在 python 中构建一个守护进程,我想获取当前活动应用程序的名称。

对于守护进程,我正在使用 Sander Marechal 的这个不错的 code snipped

当我不将应用程序作为守护程序运行时,以下行在 OS X 10.7 上完美运行,尽管文档说“activeApplication()”在 10.6+ 上已弃用

activeAppName = str(NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName'])

但是,一旦我将应用程序作为守护程序运行,应用程序就会崩溃。

但是,当我只这样做时,守护程序不会崩溃

workspace = str(NSWorkspace.sharedWorkspace())

返回:

<NSWorkspace: 0x7ffe7cc013c0>

所以我的问题是:

  1. 为什么它只作为守护进程崩溃?
  2. 如何通过python获取活动应用程序 OS X 10.7(也可以与守护进程一起使用;-))?

我不明白错误信息,但也许你们中的一个人明白:

Process:         Python [7920]
Path:            /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Identifier:      Python
Version:         ??? (???)
Code Type:       X86-64 (Native)
Parent Process:  ??? [1]

Date/Time:       2012-02-29 23:35:25.202 +0100
OS Version:      Mac OS X 10.7.3 (11D50b)
Report Version:  9

Interval Since Last Report:          818421 sec
Crashes Since Last Report:           21
Per-App Crashes Since Last Report:   15
Anonymous UUID:                      05B412BD-4629-472B-964D-BE4A88B06DD1

Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000108

VM Regions Near 0x108:
--> 
    __TEXT                 0000000102e90000-0000000102e91000 [    4K] r-x/rwx SM=COW  /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python

Application Specific Information:
*** single-threaded process forked ***
objc[7918]: garbage collection is OFF

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libdispatch.dylib               0x00007fff8ceb7ce9 _dispatch_wakeup + 108
1   libdispatch.dylib               0x00007fff8ceba876 _dispatch_resume_slow + 20
2   com.apple.CoreServices.CarbonCore   0x00007fff8d34f919 _ZL22connectToCoreServicesDv + 269
3   com.apple.CoreServices.CarbonCore   0x00007fff8d34f7d5 _ZL9getStatusv + 24
4   com.apple.CoreServices.CarbonCore   0x00007fff8d34f74f scCreateSystemServiceVersion + 50
5   com.apple.LaunchServices        0x00007fff90b5ace1 _ZL45SetupCoreApplicationServicesCommunicationPortv + 147
6   com.apple.LaunchServices        0x00007fff90b5b37a getProcessDispatchTable() + 19
7   com.apple.LaunchServices        0x00007fff90b56de0 LSClientSideSharedMemory::GetClientSideSharedMemory(LSSessionID, bool) + 158
8   com.apple.LaunchServices        0x00007fff90b6b152 _LSCopyFrontApplication + 42
9   com.apple.AppKit                0x00007fff899adc5d -[NSWorkspace activeApplication] + 26
10  libffi.dylib                    0x00007fff91df2e7c ffi_call_unix64 + 76
11  libffi.dylib                    0x00007fff91df3ae9 ffi_call + 728
12  _objc.so                        0x00000001031c7d60 PyObjCFFI_Caller + 2272
13  _objc.so                        0x00000001031dd169 0x1031ae000 + 192873
14  org.python.python               0x0000000102ea0d32 PyObject_Call + 97
15  org.python.python               0x0000000102f20f63 PyEval_EvalFrameEx + 14353
16  org.python.python               0x0000000102f23df7 0x102e99000 + 568823
17  org.python.python               0x0000000102f20e0a PyEval_EvalFrameEx + 14008
18  org.python.python               0x0000000102f23df7 0x102e99000 + 568823
19  org.python.python               0x0000000102f20e0a PyEval_EvalFrameEx + 14008
20  org.python.python               0x0000000102f23cd8 PyEval_EvalCodeEx + 1996
21  org.python.python               0x0000000102f23d4d PyEval_EvalCode + 54
22  org.python.python               0x0000000102f3b08f 0x102e99000 + 663695
23  org.python.python               0x0000000102f3b14f PyRun_FileExFlags + 157
24  org.python.python               0x0000000102f3c2a2 PyRun_SimpleFileExFlags + 392
25  org.python.python               0x0000000102f4c2af Py_Main + 2715
26  org.python.python               0x0000000102e90e88 0x102e90000 + 3720

【问题讨论】:

    标签: python objective-c osx-lion daemon pyobjc


    【解决方案1】:

    我对此进行了一些测试,我认为您的问题可能是您将此工具守护进程的方式,然后尝试进行需要可能不可用的 Windows 服务的调用。此处的此链接暗示了这种情况:http://grokbase.com/t/python/pythonmac-sig/08axst378p/appscript-and-launching-apps-from-background-only-python-processes

    我首先使用您的守护程序脚本测试了这个理论,并通过 AppleScript 调用osascript 来查找活动应用程序:

    from subprocess import Popen, PIPE
    
    cmd = """osascript \
        -e 'tell application "System Events"' \
        -e 'set app_name to name of the first process whose frontmost is true' \
        -e 'end tell' """
    v = Popen(cmd, shell=True, stdout=PIPE).stdout.read()
    

    Popen 是一种在子进程中启动系统命令并能够检查其返回码或读取其输出(或发送输入)http://docs.python.org/library/subprocess.html 的方法。 . Osascript 是一个用于调用苹果脚本的命令行工具。

    对我来说,这是因为它启动了一个我认为是否可以访问窗口服务器的新子进程?

    然后我创建了一个launchd plist,而不是使用您的守护程序脚本。这有效:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.company.test</string>
        <key>Nice</key>
        <integer>1</integer>
        <key>OnDemand</key>
        <false/>
        <key>Program</key>
        <string>/path/to/script.py</string>
    </dict>
    </plist>
    

    Launchd 是 OSX 守护进程管理器,它似乎确实以可以完全访问窗口服务器的方式启动程序。

    对于script.py,我只是让它循环,将最前面的应用程序名称写入文件并休眠。

    更新

    既然您提到您的 pyobjc 方法已被弃用,而且您似乎喜欢 applescript 方法,我想我会使用appscript - the python bindings to apple script 来采用一种 Python 的方式来做到这一点

    from appscript import app, its
    activeApp = app('System Events').processes[its.frontmost == True].first()
    print activeApp
    
    #result
    app(u'/System/Library/CoreServices/System Events.app').application_processes[u'Terminal']
    

    activeApp 是一个代表最前面的应用程序的对象,由系统事件应用程序报告。

    【讨论】:

    • 谢谢,这行得通,但由于我从未使用过 Applescript 和 Popen,你能简要解释一下 Popen 的工作原理吗?
    • 已更新。抱歉,我假设您已经知道 popen。您已经开始编写守护程序脚本并使用 pyobjc,所以我想您应该已经了解 popen。 :-)
    • 谢谢!我认为 launchd / launchctl 正是我所需要的。既然你知道如何编写这些文件,你能推荐一些好的启动教程吗?
    • 老实说,我在编写launchd plist 文件或任何东西方面并不是很有经验。我刚刚从 LaunchAgents 目录中抓取了一个并对其进行了编辑。但显然有一个非常便宜的应用程序可以为您生成它们:peterborgapps.com/lingon
    • @ka2011r:查看我的更新,了解使用 appscript apple 脚本 python 绑定的非常酷的示例。
    【解决方案2】:

    崩溃最终发生在 libdispatch 中,看起来它与共享内存有关;查看调用堆栈中的 GetClientSideSharedMemory 调用。所以看起来你的守护进程代码与 OS X 内置的grand central dispatch 技术相冲突。

    看看python daemon 模块。它执行您正在使用的代码 sn-p 忽略的事情(符合PEP 3143)。

    由于 OS X 基本上是一个带有额外花里胡哨的 UNIX,因此在尝试将程序作为守护程序运行时,您可能需要添加一些 OS X 特定的步骤。

    您可以研究在 OS X 下工作的其他守护程序的源代码,例如后缀。

    【讨论】:

      猜你喜欢
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多