Как я могу нормализовать / свернуть пути или URL в Python независимым от ОС способом? - PullRequest
5 голосов
/ 25 января 2010

Я пытался использовать os.normpath для преобразования http://example.com/a/b/c/../ в http://example.com/a/b/, но он не работает в Windows, потому что он конвертирует косую черту в обратную косую черту.

Ответы [ 3 ]

8 голосов
/ 25 января 2010

Вот как это сделать

>>> 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.

5 голосов
/ 11 ноября 2016

Ни urljoin, ни posixpath.normpath не выполняют работу должным образом . urljoin заставляет вас присоединяться к чему-либо, и не обрабатывает абсолютные пути или чрезмерные .. s правильно. posixpath.normpath сворачивает несколько косых черт и удаляет завершающие косые черты, которые не должны делать URL-адреса.


Следующая функция полностью разрешает URL-адреса, корректно обрабатывая как . s, так и .. s в соответствии с 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/'

Для получения дополнительной информации о соображениях, которые необходимо учитывать при разрешении URL-адресов, см. аналогичный ответ, который я написал ранее по этому вопросу .

2 голосов
/ 25 января 2010

принято из модуля os "- os.path - это один из модулей posixpath, или ntpath", в вашем случае явно используется posixpath.

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