【问题标题】:What replaces the now-deprecated Carbon.File.FSResolveAliasFile in Python on OSX?什么替代了 OSX 上 Python 中现已弃用的 Carbon.File.FSResolveAliasFile?
【发布时间】:2014-01-20 21:44:31
【问题描述】:

在 Python 2 中,我可以使用以下代码来解析 MacOS 别名或符号链接:

from Carbon import File
File.FSResolveAliasFile(alias_fp, True)[0].as_pathname()

其中 alias_fp 是我感兴趣的文件的路径,存储为字符串 (source)。

但是,the documentation cheerfully tells me that the whole Carbon family of modules is deprecated。我应该改用什么?

编辑:我相信下面的代码是 PyObjC 方法朝着正确方向迈出的一步。它不解析别名,但似乎可以检测到它们。

from AppKit import NSWorkspace
def is_alias (path):
    uti, err = NSWorkspace.sharedWorkspace().typeOfFile_error_(
        os.path.realpath(path), None)
    if err:
        raise Exception(unicode(err))
    else:
        return "com.apple.alias-file" == uti

(source)

不幸的是,我无法让@Milliways 的解决方案发挥作用(对 Cocoa 一无所知),stuff I find elsewhere on the internet 看起来要复杂得多(也许它正在处理各种边缘情况?)。

【问题讨论】:

    标签: python macos cocoa symlink macos-carbon


    【解决方案1】:

    PyObjC 桥允许您访问 NSURL 的书签处理,它是别名的现代(向后兼容)替代:

    import os.path
    from Foundation import *
    
    def target_of_alias(path):
        url = NSURL.fileURLWithPath_(path)
        bookmarkData, error = NSURL.bookmarkDataWithContentsOfURL_error_(url, None)
        if bookmarkData is None:
            return None
        opts = NSURLBookmarkResolutionWithoutUI | NSURLBookmarkResolutionWithoutMounting
        resolved, stale, error = NSURL.URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_(bookmarkData, opts, None, None, None)
        return resolved.path()
    
    def resolve_links_and_aliases(path):
        while True:
            alias_target = target_of_alias(path)
            if alias_target:
                path = alias_target
                continue
            if os.path.islink(path):
                path = os.path.realpath(path)
                continue
            return path
    

    【讨论】:

    • 我添加了一个解析别名和符号链接的包装函数。
    【解决方案2】:

    以下 Cocoa 代码将解析别名。

    NSURL *targetOfAlias(NSURL *url) {
        CFErrorRef *errorRef = NULL;
        CFDataRef bookmark = CFURLCreateBookmarkDataFromFile (NULL, (__bridge CFURLRef)url, errorRef);
        if (bookmark == nil) return nil;
        CFURLRef resolvedUrl = CFURLCreateByResolvingBookmarkData (NULL, bookmark, kCFBookmarkResolutionWithoutUIMask, NULL, NULL, false, errorRef);
        CFRelease(bookmark);
        return CFBridgingRelease(resolvedUrl);
    }
    

    我不知道如何从 Python 调用 Cocoa 框架,但我相信有人已经做到了

    以下链接显示了解析别名或符号链接https://stackoverflow.com/a/21151368/838253的代码

    【讨论】:

    • @SevenBits 我同意这并没有解决问题,但解决了其他问题。别名可使用CoreFoundation 而非Carbon 解析。这对可以编写 Python 包装器的人很有用。
    • 很难用任何语言解决这个问题——至少这有助于我用 c++ 完成它。让我摆脱那个downvote..
    • 上述解决方案由Apple's Documentation on FSResolveAliasFile 中的已弃用 通知支持。
    【解决方案3】:

    这些模块使用的 API 似乎已被 Apple 弃用。您应该改用 POSIX API。

    os.path.realpath(FILE_OBJECT.name)
    

    【讨论】:

    • 抱歉——我过早地将此标记为已接受。它似乎适用于符号链接,但不适用于别名。现在我想起来了,我相信别名是特定于 Mac 的,因此 POSIX 工具不太可能很好地处理。
    • 我不相信有一个标准的库方法可以做到这一点。由于苹果删除/贬低了支持它们的 API,所有 OSX 特定模块都已在 Python 3 中删除。
    • pythonhosted.org/pyobjc 可能对另一个答案有用。同样,这不是标准库选项,但如果您进行多次 Cocoa 调用,这就是方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    • 2012-03-28
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    相关资源
    最近更新 更多