Na przykład chcę dołączyć ścieżkę prefiksu do ścieżek zasobów, takich jak /js/foo.js.
Chcę, aby wynikowa ścieżka była względna w stosunku do katalogu głównego serwera. W powyższym przykładzie, jeśli przedrostkiem byłby „media”, chciałbym, aby wynikiem był /media/js/foo.js.
os.path.join robi to naprawdę dobrze, ale sposób łączenia ścieżek zależy od systemu operacyjnego. W tym przypadku wiem, że moim celem jest sieć internetowa, a nie lokalny system plików.
Czy istnieje najlepsza alternatywa podczas pracy ze ścieżkami, o których wiesz, że będą używane w adresach URL? Czy os.path.join będzie działać wystarczająco dobrze? Czy powinienem po prostu skręcić własną?
os.path.join
nie będzie działać. Ale zwykłe łączenie za pomocą/
znaku powinno działać we wszystkich przypadkach -/
to standardowy separator ścieżki w HTTP zgodnie ze specyfikacją.Odpowiedzi:
Ponieważ z komentarzy opublikowanych przez OP wynika, że nie chce zachowywać „bezwzględnych adresów URL” w złączeniu (co jest jednym z kluczowych zadań
urlparse.urljoin
;-), radziłbym tego unikać.os.path.join
byłoby również złe, dokładnie z tego samego powodu.Więc użyłbym czegoś w rodzaju
'/'.join(s.strip('/') for s in pieces)
(jeśli interlinia/
również musi być zignorowana - jeśli wiodąca część musi być w specjalnym opakowaniu, to oczywiście jest to wykonalne ;-).źródło
os.path.join('http://media.com', 'content')
powróci świathttp://media.com\content
.Możesz użyć
urllib.parse.urljoin
:Ale uwaga :
Powodem, dla którego otrzymujesz różne wyniki
/js/foo.js
ijs/foo.js
jest to, że pierwszy zaczyna się od ukośnika, który oznacza, że zaczyna się już w katalogu głównym witryny.W Pythonie 2 musisz to zrobić
źródło
urljoin
kiedykolwiek usuwa się „/”. Jeśli zadzwonię,urlparse.urljoin('/media/', '/js/foo.js')
zwracana wartość to „/js/foo.js”. Usunięto wszystkie media, a nie zduplikowany znak „/”. Wurlparse.urljoin('/media//', 'js/foo.js')
rzeczywistości zwraca „/media//js/foo.js”, więc żadne duplikaty nie zostały usunięte.urljoin
nie służy do łączenia adresów URL. Służy do rozwiązywania względnych adresów URL, jakie można znaleźć w dokumentach HTML itp.Jak mówisz,
os.path.join
łączy ścieżki w oparciu o bieżący system operacyjny.posixpath
jest podstawowym modułem używanym w systemach POSIX w przestrzeni nazwos.path
:Możesz więc po prostu zaimportować i używać
posixpath.join
zamiast adresów URL, które są dostępne i będą działać na dowolnej platformie .Edycja: Sugestia @ Pete'a jest dobra, możesz alias importu dla zwiększenia czytelności
Edycja: myślę, że jest to wyjaśnione lub przynajmniej pomogło mi to zrozumieć, jeśli spojrzysz na źródło
os.py
(kod tutaj pochodzi z Pythona 2.7.11, a dodatkowo przyciąłem kilka bitów). Istnieją warunkowe importy wos.py
tym, które wybierają moduł ścieżki do użycia w przestrzeni nazwos.path
. Wszystkie moduły bazowe (posixpath
,ntpath
,os2emxpath
,riscospath
), które mogą być importowaneos.py
, alias jakpath
, istnieją i istnieć być stosowany we wszystkich systemach.os.py
to po prostu wybranie jednego z modułów do użycia w przestrzeni nazwos.path
w czasie wykonywania w oparciu o bieżący system operacyjny.źródło
from posixpath import join as urljoin
ładnie tworzy aliasy do czegoś łatwego do odczytania.To ładnie działa:
źródło
Funkcja basejoin w pakiecie urllib może być tym, czego szukasz.
Edycja: nie zauważyłem wcześniej, ale urllib.basejoin wydaje się mapować bezpośrednio do urlparse.urljoin, co czyni go preferowanym.
źródło
Używając furla
pip install furl
będzie to:źródło
.url
na końcu:furl.furl('/media/path/').add(path='js/foo.js').url
furl('/media/path/').add(path=furl('/js/foo.js').path).url
bofurl('/media/path/').add(path='/js/foo.js').url
jest/media/path//js/foo.js
Wiem, że to trochę więcej, niż prosił OP, jednak miałem elementy do następującego adresu URL i szukałem prostego sposobu, aby do nich dołączyć:
Rozglądając się:
Więc oprócz ścieżki łączenia, na którą już udzielono odpowiedzi w innych odpowiedziach, Aby uzyskać to, czego szukałem, wykonałem następujące czynności:
Zgodnie z dokumentacją zajmuje DOKŁADNIE 5-częściową krotkę.
Z następującym formatem krotki:
źródło
Rune Kaagaard dostarczył świetne i kompaktowe rozwiązanie, które działało dla mnie, rozszerzyłem je trochę:
Pozwala to na łączenie wszystkich argumentów bez względu na końcowe i końcowe ukośniki, przy jednoczesnym zachowaniu ostatniego ukośnika, jeśli jest obecny.
źródło
return "/".join([str(x).strip("/") for x in args]) + trailing_slash
Aby poprawić nieco reakcję Alexa Martelliego, poniższe elementy nie tylko usuwają dodatkowe ukośniki, ale także zachowują końcowe (końcowe) ukośniki, które czasami mogą być przydatne:
Nie jest jednak tak łatwy do odczytania i nie usunie wielu dodatkowych końcowych ukośników.
źródło
Wszystkie powyższe rozwiązania nie podobały mi się, więc wymyśliłem własne. Ta wersja zapewnia łączenie części za pomocą pojedynczego ukośnika i pozostawia same początkowe i końcowe ukośniki. Nie
pip install
, nie maurllib.parse.urljoin
dziwności.źródło
Używanie furl i regex (Python 3)
źródło