2012-02-29 85 views
3

我想在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> 

所以我的問題是:

  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 

回答

3

我對此做了一些測試,我認爲你的問題可能是你守護這個工具,然後試圖打電話,需要可能不可用的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() 

POPEN是發射方式:http://grokbase.com/t/python/pythonmac-sig/08axst378p/appscript-and-launching-apps-from-background-only-python-processes

我一直在使用你的後臺程序腳本,使一個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應用程序報告的最前面的應用程序的對象。

+0

謝謝,這是有效的,但是因爲我從來沒有和Applescript和Popen一起工作過,你能不能簡短地解釋一下Popen是如何工作的? – kadrian 2012-03-01 14:43:39

+0

已更新。對不起,我假設你已經知道了popen。你已經在做守護進程腳本和使用pyobjc,所以我想你已經知道了popen。 :-) – jdi 2012-03-01 15:58:39

+0

謝謝!我認爲launchd/launchctl正是我所需要的。既然你知道如何編寫這些文件,你能推薦一些很好的啓動教程嗎? – kadrian 2012-03-01 17:08:49

1

崩潰,最終發生在libdispatch,它看起來像它是與共享內存;請參閱調用堆棧中的GetClientSideSharedMemory調用。因此,看起來您的守護程序代碼與OS X內置的grand central dispatch技術相違背。

看看python daemon模塊。它執行的內容(符合PEP 3143)代表您正在使用的代碼段忽略。

由於OS X基本上是一個額外的花裏胡哨的UNIX,因此當您嘗試將程序作爲守護程序運行時,您可能需要添加一些OS X的特定步驟。

您可以研究在OS X下工作的其他守護進程的源代碼,例如,後綴。

相關問題