如何以独立于操作系统的方式规范化/折叠Python中的路径或URL?

时间:2010-01-25 09:30:59

标签: python url path normalize

我尝试使用os.normpathhttp://example.com/a/b/c/../转换为http://example.com/a/b/,但它在Windows上不起作用,因为它确实将斜杠转换为反斜杠。

3 个答案:

答案 0 :(得分:8)

以下是如何操作

>>> import urlparse
>>> urlparse.urljoin("ftp://domain.com/a/b/c/d/", "../..")
'ftp://domain.com/a/b/'
>>> urlparse.urljoin("ftp://domain.com/a/b/c/d/e.txt", "../..")
'ftp://domain.com/a/b/'    

请记住urljoin在最后/之前考虑路径/目录 - 在此之后是文件名(如果有的话)。

此外,请勿向第二个参数添加前导/,否则您将无法获得预期结果。

os.path模块取决于平台,但对于仅使用斜杠但不使用URL的文件路径,您可以使用posixpath,normpath

答案 1 :(得分:5)

urljoinposixpath.normpath都无法正常完成工作urljoin强制您加入某些内容,并且无法正确处理绝对路径或过度..posixpath.normpath折叠多个斜杠并删除尾部斜杠,这两个都是URL不应该做的事情。

以下功能完全解析网址,根据RFC 3986以正确的方式处理...

try:
    # Python 3
    from urllib.parse import urlsplit, urlunsplit
except ImportError:
    # Python 2
    from urlparse import urlsplit, urlunsplit

def resolve_url(url):
    parts = list(urlsplit(url))
    segments = parts[2].split('/')
    segments = [segment + '/' for segment in segments[:-1]] + [segments[-1]]
    resolved = []
    for segment in segments:
        if segment in ('../', '..'):
            if resolved[1:]:
                resolved.pop()
        elif segment not in ('./', '.'):
            resolved.append(segment)
    parts[2] = ''.join(resolved)
    return urlunsplit(parts)

然后,您可以在完整的URL上调用它,如下所示。

>>> resolve_url("http://example.com/dir/../../thing/.")
'http://example.com/thing/'

有关解析网址时必须考虑的注意事项的详细信息,请参阅a similar answer I wrote earlier on the subject

答案 2 :(得分:2)

采用os模块“ - os.path是模块posixpath或ntpath”之一,在你的情况下使用posixpath显式。

   >>> import posixpath
    >>> posixpath.normpath("/a/b/../c")
    '/a/c'
    >>>