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

bog*_*dan 5 python url path normalize

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

sor*_*rin 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/'    
Run Code Online (Sandbox Code Playgroud)

请记住,urljoin考虑一个路径/目录直到最后/- 在此之后是文件名,如果有的话.

此外,不要添加前导/到第二个参数,否则您将无法获得预期的结果.

os.path模块是平台相关的,但对于只使用斜杠但不使用URL的文件路径posixpath,normpath.


obs*_*kyr 6

urljoin没有posixpath.normpath正确的工作.urljoin强迫你加入某些东西,并且不能..正确处理绝对路径或过多的路径.posixpath.normpath折叠多个斜杠并删除尾部斜杠,这两者都是URL不应该做的事情.


以下函数完全解析URL,根据RFC 3986以正确的方式处理.s和..s .

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)
Run Code Online (Sandbox Code Playgroud)

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

>>> resolve_url("http://example.com/dir/../../thing/.")
'http://example.com/thing/'
Run Code Online (Sandbox Code Playgroud)

有关解析URL时必须考虑的注意事项的更多信息,请参阅我之前在此主题上编写的类似答案.