Python os.path.join () в списке

97

я могу сделать

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

Но когда я сделаю

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

Что мне здесь не хватает?

АТОзТОА
источник

Ответы:

197

Проблема в том, что аргумент os.path.joinне принимается list, это должны быть отдельные аргументы.

Здесь *в игру вступает оператор 'splat' ...

я могу сделать

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(*s)
'c:/home\\foo\\bar\\some.txt'
АТОзТОА
источник
10
еще немного контекста для splat: docs.python.org/2/tutorial/…
A.Wan
3
Обратите внимание, что я попытался использовать это, чтобы удалить последнюю часть полного пути. Это привело к ошибке (в Mac), так как не было первой косой черты в /Users/.... Чтобы решить эту проблему, я добавил эту ведущую косую черту вручную на случай, если кто-то
столкнется
23

Предполагая, что joinэто не было разработано таким образом (как указано в ATOzTOA), и для этого требовалось только два параметра, вы все равно могли бы использовать встроенный reduce:

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

Такой же результат, как:

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

Просто для полноты и образовательных целей (и для других ситуаций, когда *не работает).

Подсказка для Python 3

reduceбыл перенесен в functoolsмодуль.

Торстен Кранц
источник
2
В Python 3 reduceбыл перемещен в functoolsмодуль на случай, если кто-то еще искал его, как и я.
Адам Бадура
Спасибо за подсказку, поправлю свой ответ.
Торстен Кранц
3
жаль, что питон все больше и больше уходит от функционального стиля вместо того, чтобы принять его и открыться. переход reduceк модулю - это заявление.
Шернандес
Даже в 2.7 можноfrom functools import reduce
duhaime
14

Я наткнулся на ситуацию, когда список может быть пуст. В таком случае:

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

Обратите внимание на первый аргумент, который не повлияет на результат.

Себастьян Мах
источник
8

Это просто метод. Вы ничего не упускаете. В официальной документации показывает , что вы можете использовать список распаковки , чтобы поставить несколько путей:

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

Обратите внимание на *sзначение только что sв os.path.join(*s). Использование звездочки вызовет распаковку списка, что означает, что каждый аргумент списка будет передан функции как отдельный аргумент.

Грег
источник
Лучше загляните в свою ссылку еще раз ;-)
Торстен Кранц
@Greg, на SO предпочтительно копировать соответствующие части в ответ, а не просто вставлять ссылку, возможно, поэтому отрицательные голоса
Шернандес
2

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

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

reduceвстроен в Python 2.x. В Python 3.x он был перемещен в itertoolsОднако принятый ответ лучше.

На этот вопрос был дан ответ ниже, но ответим, есть ли у вас список элементов, которые необходимо объединить.

Нишант
источник