Python os.path.join () na liście

98

potrafię

>>> os.path.join("c:/","home","foo","bar","some.txt")
'c:/home\\foo\\bar\\some.txt'

Ale kiedy robię

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(s)
['c:/', 'home', 'foo', 'bar', 'some.txt']

Czego tu brakuje?

ATOzTOA
źródło

Odpowiedzi:

199

Problem w tym, os.path.joinże nie przyjmuje się listargumentu, muszą to być oddzielne argumenty.

Tutaj *do gry wkracza operator `` splat '' ...

potrafię

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(*s)
'c:/home\\foo\\bar\\some.txt'
ATOzTOA
źródło
10
trochę więcej kontekstu dla splat: docs.python.org/2/tutorial/ ...
A. Wan
3
Zauważ, że próbowałem użyć tego do usunięcia ostatniej części pełnej ścieżki. Spowodowało to błąd (na Macu), ponieważ brakowało pierwszego ukośnika w /Users/.... Aby to rozwiązać, dodałem ręcznie ten ukośnik, na wypadek gdyby ktoś
napotkał
24

Zakładając, że joinnie został zaprojektowany w ten sposób (a tak jest, jak wskazała ATOzTOA) i wymagał tylko dwóch parametrów, nadal można było korzystać z wbudowanego reduce:

>>> reduce(os.path.join,["c:/","home","foo","bar","some.txt"])
'c:/home\\foo\\bar\\some.txt'

Takie same dane wyjściowe jak:

>>> os.path.join(*["c:/","home","foo","bar","some.txt"])
'c:/home\\foo\\bar\\some.txt' 

Tylko dla kompletności i ze względów edukacyjnych (oraz w innych sytuacjach, w których *nie działa).

Wskazówka dla Pythona 3

reducezostał przeniesiony do functoolsmodułu.

Thorsten Kranz
źródło
2
W Pythonie 3 reducezostał przeniesiony do functoolsmodułu na wypadek, gdyby ktoś inny szukał go tak jak ja.
Adam Badura,
Dziękuję za podpowiedź, dostosuję odpowiedź.
Thorsten Kranz
3
Szkoda, że ​​Python coraz bardziej oddala się od funkcjonalnego stylu, zamiast go przyjmować i otwierać. przejście reducedo modułu jest instrukcją.
SHernandez
Nawet w 2.7 możnafrom functools import reduce
duhaime
14

Natknąłem się na sytuację, w której lista mogła być pusta. W tym wypadku:

os.path.join('', *the_list_with_path_components)

Zwróć uwagę na pierwszy argument, który nie zmieni wyniku.

Sebastian Mach
źródło
9

To tylko metoda. Niczego nie brakuje. W oficjalnej dokumentacji wynika, że można użyć listy rozpakowywania zasilać kilka ścieżek:

s = "c:/,home,foo,bar,some.txt".split(",")
os.path.join(*s)

Zwróć uwagę na *sintead of just sin os.path.join(*s). Użycie gwiazdki spowoduje rozpakowanie listy, co oznacza, że ​​każdy argument listy zostanie przekazany funkcji jako oddzielny argument.

Greg
źródło
Lepiej spójrz jeszcze raz na swój link ;-)
Thorsten Kranz
@Greg zaleca się, aby SO skopiował odpowiednie części do odpowiedzi, a nie tylko wkleił link, może dlatego głosy przeciwne
SHernandez
2

Można to również potraktować jako prostą operację redukcji mapy, jeśli chcesz spojrzeć na to z perspektywy programowania funkcjonalnego.

import os
folders = [("home",".vim"),("home","zathura")]
[reduce(lambda x,y: os.path.join(x,y), each, "") for each in folders]

reducejest wbudowany w Python 2.x. W Pythonie 3.x został przeniesiony do itertoolsJednak zaakceptowana odpowiedź jest lepsza.

Odpowiedź na to pytanie znajduje się poniżej, ale odpowiadam, jeśli masz listę elementów, które należy połączyć.

Nishant
źródło