如何在Python中以与操作系统无关的方式归一化/压缩路径或URL?
我试着用 os.normpath
来把 http://example.com/a/b/c/../
转换成 http://example.com/a/b/
,但是在Windows上不行,因为它把斜杠变成了反斜杠。
3 个回答
2
这段话的意思是,"os"模块里有一个叫做"os.path"的部分,它实际上是由"posixpath"或"ntpath"这两个模块组成的。在你的情况下,明确使用的是"posixpath"。
>>> import posixpath
>>> posixpath.normpath("/a/b/../c")
'/a/c'
>>>
8
既然 urljoin
和 posixpath.normpath
都不能正确处理这个问题。urljoin
要求你必须和某个东西连接,而且对绝对路径或过多的 ..
处理得不太好。posixpath.normpath
会把多个斜杠合并,并去掉末尾的斜杠,这些都是网址不应该做的事情。
下面这个函数可以完全解析网址,正确处理 .
和 ..
,符合 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)
你可以像下面这样在一个完整的网址上调用它。
>>> resolve_url("http://example.com/dir/../../thing/.")
'http://example.com/thing/'
想了解更多关于解析网址时需要考虑的事项,可以查看 我之前写的一个类似的回答。
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
模块是和操作系统有关的,但如果你只是在处理文件路径(不是网址),可以使用 posixpath
和 normpath
。