Python os.path.join () em uma lista

90

eu posso fazer

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

Mas quando eu faço

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

O que estou perdendo aqui?

ATOzTOA
fonte

Respostas:

189

O problema é os.path.joinque não toma um listcomo argumento, tem que ser argumentos separados.

É aqui que *o operador 'splat' entra em jogo ...

eu posso fazer

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(*s)
'c:/home\\foo\\bar\\some.txt'
ATOzTOA
fonte
10
um pouco mais de contexto para splat: docs.python.org/2/tutorial/…
A.Wan
3
Observe que tentei usar isso para remover a última parte de um caminho completo. Isso resultou em um erro (no Mac), pois faltava a primeira barra em /Users/.... Para resolver, adicionei aquela barra inicial manualmente, caso alguém enfrente o mesmo problema ...
J0ANMM
22

Supondo que joinnão foi projetado dessa forma (o que é, como ATOzTOA apontou), e levou apenas dois parâmetros, você ainda pode usar o integrado reduce:

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

Mesma saída como:

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

Apenas por razões de exaustividade e educacional (e para outras situações onde *não funciona).

Dica para Python 3

reducefoi movido para o functoolsmódulo.

Thorsten Kranz
fonte
2
No Python 3 reducefoi movido para o functoolsmódulo, caso alguém mais estivesse procurando por ele como eu.
Adam Badura
Obrigado pela dica, vou ajustar minha resposta.
Thorsten Kranz
3
pena que o python se afasta cada vez mais do estilo funcional em vez de abraçá-lo e se abrir. mudar reducepara um módulo é uma declaração.
SHernandez
Mesmo em 2.7 pode-sefrom functools import reduce
duhaime
12

Tropecei na situação em que a lista pode estar vazia. Nesse caso:

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

Observe o primeiro argumento, que não alterará o resultado.

Sebastian Mach
fonte
8

É apenas o método. Você não está perdendo nada. A documentação oficial mostra que você pode usar a descompactação de lista para fornecer vários caminhos:

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

Observe o início *sde apenas sem os.path.join(*s). O uso do asterisco irá desencadear a descompactação da lista, o que significa que cada argumento da lista será fornecido para a função como um argumento separado.

Greg
fonte
Melhor olhar seu link mais uma vez ;-)
Thorsten Kranz
@Greg é preferível no SO copiar as partes relevantes na resposta e não apenas colar um link, talvez, portanto, os
votos negativos
2

Isso também pode ser considerado uma operação simples de redução de mapa, se você quiser pensar nisso de uma perspectiva de programação funcional.

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

reduceestá embutido no Python 2.x. No Python 3.x, ele foi movido para itertoolsNo entanto, a resposta aceita é melhor.

Isso foi respondido abaixo, mas respondendo se você tiver uma lista de itens que precisam ser unidos.

Nishant
fonte