简体   繁体   English

在OS X上,是否可以从纯Python获取用户库目录?

[英]On OS X, is it possible to get the user library directory from pure Python?

I'm writing a pure Python library, and for various reasons I would very much like to avoid asking users to install any binary extensions. 我正在编写一个纯Python库,出于各种原因,我非常想避免要求用户安装任何二进制扩展名。 However, when running on OS X, I would also like to locate the user library directory ( ~/Library ) so I can store some configuration data there, and my understanding is that for Very Valid And Vague But Important Reasons the proper way to do this is not by just writing ~/Library in my code, but instead by asking OS X where the directory is with some code like 但是,在OS X上运行时,我也想找到用户库目录( ~/Library ),以便在其中存储一些配置数据,我的理解是,对于“非常有效且含糊但重要的原因”,正确的做法是这不仅仅是通过在我的代码中编写~/Library ,而是通过询问OS X目录中包含一些代码的地方,例如

[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
                                     NSUserDomainMask,
                                     YES)
 objectAtIndex:0];

Of course, this code is Objective-C, not Python, so I can't just use it directly. 当然,此代码是Objective-C,而不是Python,因此我不能直接使用它。 And if it were plain C, I'd just use ctypes to call it from Python, but it isn't. 如果它是纯C语言,我只会使用ctypes从Python调用它,但事实并非如此。 Is there any way to make this call from Python, without writing an extension module in Objective-C or requiring the user to install some extension module like PyObjC ? 有什么方法可以从Python进行此调用,而无需在Objective-C中编写扩展模块或要求用户安装某些扩展模块(如PyObjC Alternatively, if I just give up and hard-code ~/Library like everyone else does, then will anything terrible happen? 或者,如果我像其他所有人一样放弃并硬编码~/Library ,那么会发生什么可怕的事情吗?

Well, it is plain C under the hood, so you can achieve the same result with ctypes module: 好吧, 它是底层的普通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)

But the universe probably won't collapse if you just use ~/Library ;) 但是如果只使用~/Library ,宇宙可能不会崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM