Ich habe versucht, os.normpath
zu verwenden, um http://example.com/a/b/c/../
in http://example.com/a/b/
zu konvertieren, aber es funktioniert nicht auf Windows, weil es den Schrägstrich in umgekehrten Schrägstrich konvertiert.Wie kann ich Pfade oder URLs in Python auf Betriebssystem-unabhängige Weise normalisieren/reduzieren?
Antwort
Hier ist, wie es Remember
>>> 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/'
zu tun, dass urljoin
ein Pfad/Verzeichnis all bis zum letzten /
betrachten - danach der Dateinamen, falls vorhanden.
Fügen Sie auch keine führende /
zum zweiten Parameter hinzu, sonst erhalten Sie nicht das erwartete Ergebnis.
os.path
Modul ist plattformabhängig, aber für Dateipfade, die nur Schrägstriche verwenden, aber keine URLs, die Sie verwenden könnten posixpath,normpath
.
übernommen von os modul "- os.path ist eines der Module posixpath oder ntpath", in Ihrem Fall explizit mit posixpath.
>>> import posixpath
>>> posixpath.normpath("https://stackoverflow.com/a/b/../c")
'/a/c'
>>>
'posixpath.normpath' tut nicht hilfreiche Dinge, wie das Entfernen von Schrägstrichen und das Erlauben eines doppelten Schrägstrichs. Ersetzt auch den leeren Pfad durch '.'. –
Weder urljoin
noch posixpath.normpath
den Job richtig. urljoin
zwingt Sie, mit etwas beizutreten, und behandelt nicht absolut Pfade oder übermäßige ..
s korrekt. posixpath.normpath
reduziert mehrere Schrägstriche und entfernt nachfolgende Schrägstriche, die URLs nicht tun sollten.
Die folgende Funktion löst vollständig URLs, beid .
s und s ..
Handhabung in korrekter Weise RFC 3986 nach.
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)
Sie können dann auf eine vollständige URL wie folgt aufrufen.
>>> resolve_url("http://example.com/dir/../../thing/.")
'http://example.com/thing/'
Weitere Informationen zu den Überlegungen, die gemacht werden müssen, wenn URLs Lösung finden a similar answer I wrote earlier on the subject.
Im Gegenteil: Wenn der zweite Parameter eine führende '/' hat, wird 'ftp: //domain.com /../ ..' zurückgegeben. Korrigieren. –