使用python守护进程获取OS X 10.7上的活动应用程序
我想在python中构建守护进程,我想获取当前活动应用程序的名称。使用python守护进程获取OS X 10.7上的活动应用程序
对于我使用这个漂亮code snipped从桑德马雷夏尔
以下行完美的作品在OS X 10.7的时候,不运行应用程序作为一个守护进程守护进程,虽然文件说,“activeApplication() “被废弃的10.6+
activeAppName = str(NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName'])
但只要我运行应用程序作为守护程序,该应用程序崩溃。
但是,守护程序不会崩溃的时候我只做
workspace = str(NSWorkspace.sharedWorkspace())
返回:
<NSWorkspace: 0x7ffe7cc013c0>
所以我的问题是:
- 为什么它会崩溃只是作为一个守护进程?
- 如何通过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
我对此做了一些测试,我认为你的问题可能是你守护这个工具,然后试图打电话,需要可能不可用的Windows服务。这里该链接暗示了这样的情况:
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()
我一直在使用你的后台程序脚本,使一个osascript
打电话找通过AppleScript的活动应用程序首先测试这个理论一个子进程中的系统命令,并能够检查其返回码或读取其输出(或发送输入)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守护进程管理器,它似乎确实在某种程度上,他们必须在windowserver的完全访问权限运行程序。
对于script.py
,我只是简单地将它循环,将最前面的应用程序名称写入文件并进行睡眠。
更新
既然你曾提到你pyobjc方法被弃用,你似乎喜欢AppleScript的方法,我想我会钉在做的Python的方式,使用appscript - the python bindings to apple script
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
是代表System Events应用程序报告的最前面的应用程序的对象。
崩溃,最终发生在libdispatch,它看起来像它是与共享内存;请参阅调用堆栈中的GetClientSideSharedMemory调用。因此,看起来您的守护程序代码与OS X内置的grand central dispatch技术相违背。
看看python daemon模块。它执行的内容(符合PEP 3143)代表您正在使用的代码段忽略。
由于OS X基本上是一个额外的花里胡哨的UNIX,因此当您尝试将程序作为守护程序运行时,您可能需要添加一些OS X的特定步骤。
您可以研究在OS X下工作的其他守护进程的源代码,例如,后缀。
谢谢,这是有效的,但是因为我从来没有和Applescript和Popen一起工作过,你能不能简短地解释一下Popen是如何工作的? – kadrian 2012-03-01 14:43:39
已更新。对不起,我假设你已经知道了popen。你已经在做守护进程脚本和使用pyobjc,所以我想你已经知道了popen。 :-) – jdi 2012-03-01 15:58:39
谢谢!我认为launchd/launchctl正是我所需要的。既然你知道如何编写这些文件,你能推荐一些很好的启动教程吗? – kadrian 2012-03-01 17:08:49