![](/img/trans.png)
[英]Python development on Mac OS X: pure Mac OS or linux in virtualbox
[英]On OS X, is it possible to get the user library directory from pure Python?
我正在編寫一個純Python庫,出於各種原因,我非常想避免要求用戶安裝任何二進制擴展名。 但是,在OS X上運行時,我也想找到用戶庫目錄( ~/Library
),以便在其中存儲一些配置數據,我的理解是,對於“非常有效且含糊但重要的原因”,正確的做法是這不僅僅是通過在我的代碼中編寫~/Library
,而是通過詢問OS X目錄中包含一些代碼的地方,例如
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask,
YES)
objectAtIndex:0];
當然,此代碼是Objective-C,而不是Python,因此我不能直接使用它。 如果它是純C語言,我只會使用ctypes
從Python調用它,但事實並非如此。 有什么方法可以從Python進行此調用,而無需在Objective-C中編寫擴展模塊或要求用戶安裝某些擴展模塊(如PyObjC
? 或者,如果我像其他所有人一樣放棄並硬編碼~/Library
,那么會發生什么可怕的事情嗎?
好吧, 它是底層的普通C語言,因此您可以使用ctypes
模塊獲得相同的結果:
from ctypes import *
NSLibraryDirectory = 5
NSUserDomainMask = 1
def NSSearchPathForDirectoriesInDomains(directory, domainMask, expand = True):
# If library path looks like framework, OS X will search $DYLD_FRAMEWORK_PATHs automatically
# There's no need to specify full path (/System/Library/Frameworks/...)
Foundation = cdll.LoadLibrary("Foundation.framework/Foundation")
CoreFoundation = cdll.LoadLibrary("CoreFoundation.framework/CoreFoundation");
_NSSearchPathForDirectoriesInDomains = Foundation.NSSearchPathForDirectoriesInDomains
_NSSearchPathForDirectoriesInDomains.argtypes = [ c_uint, c_uint, c_bool ]
_NSSearchPathForDirectoriesInDomains.restype = c_void_p
_CFRelease = CoreFoundation.CFRelease
_CFRelease.argtypes = [ c_void_p ]
_CFArrayGetCount = CoreFoundation.CFArrayGetCount
_CFArrayGetCount.argtypes = [ c_void_p ]
_CFArrayGetCount.restype = c_uint
_CFArrayGetValueAtIndex = CoreFoundation.CFArrayGetValueAtIndex
_CFArrayGetValueAtIndex.argtypes = [ c_void_p, c_uint ]
_CFArrayGetValueAtIndex.restype = c_void_p
_CFStringGetCString = CoreFoundation.CFStringGetCString
_CFStringGetCString.argtypes = [ c_void_p, c_char_p, c_uint, c_uint ]
_CFStringGetCString.restype = c_bool
kCFStringEncodingUTF8 = 0x08000100
# MAX_PATH on POSIX is usually 4096, so it should be enough
# It might be determined dynamically, but don't bother for now
MAX_PATH = 4096
result = []
paths = _NSSearchPathForDirectoriesInDomains(directory, domainMask, expand)
# CFArrayGetCount will crash if argument is NULL
# Even though NSSearchPathForDirectoriesInDomains never returns null, we'd better check it
if paths:
for i in range(0, _CFArrayGetCount(paths)):
path = _CFArrayGetValueAtIndex(paths, i)
buff = create_string_buffer(MAX_PATH)
if _CFStringGetCString(path, buff, sizeof(buff), kCFStringEncodingUTF8):
result.append(buff.raw.decode('utf-8').rstrip('\0'))
del buff
_CFRelease(paths)
return result
print NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask)
但是如果只使用~/Library
,宇宙可能不會崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.