Por exemplo, quero juntar um caminho de prefixo para caminhos de recursos como /js/foo.js.
Quero que o caminho resultante seja relativo à raiz do servidor. No exemplo acima, se o prefixo fosse "media", gostaria que o resultado fosse /media/js/foo.js.
os.path.join faz isso muito bem, mas como ele une caminhos depende do sistema operacional. Nesse caso, sei que estou visando a web, não o sistema de arquivos local.
Existe uma alternativa melhor quando você está trabalhando com caminhos que sabe que serão usados em URLs? O os.path.join funcionará bem o suficiente? Devo apenas lançar o meu próprio?
os.path.join
não funciona. Mas simplesmente juntar pelo/
caractere deve funcionar em todos os casos -/
é o separador de caminho padrão em HTTP de acordo com a especificação.Respostas:
Visto que, a partir dos comentários que o OP postou, parece que ele não deseja preservar "URLs absolutos" no join (que é um dos principais trabalhos de
urlparse.urljoin
;-), eu recomendo evitar isso.os.path.join
também seria ruim, exatamente pelo mesmo motivo.Então, eu usaria algo como
'/'.join(s.strip('/') for s in pieces)
(se o condutor/
também deve ser ignorado - se o condutor deve ter uma caixa especial, isso também é viável, é claro ;-).fonte
os.path.join('http://media.com', 'content')
wourd returnhttp://media.com\content
.Você pode usar
urllib.parse.urljoin
:Mas cuidado :
A razão pela qual você obtém resultados diferentes de
/js/foo.js
ejs/foo.js
é porque o primeiro começa com uma barra que significa que já começa na raiz do site.No Python 2, você deve fazer
fonte
urljoin
se remove '/'. Se eu chamá-lo comurlparse.urljoin('/media/', '/js/foo.js')
o valor retornado é '/js/foo.js'. Ele removeu todas as mídias, não a duplicata '/'. Naurlparse.urljoin('/media//', 'js/foo.js')
verdade, retorna '/media//js/foo.js', então nenhuma duplicata removida.urljoin
não é para juntar URLs. É para resolver URLs relativos como encontrados em documentos HTML, etc.Como você disse,
os.path.join
junta caminhos com base no sistema operacional atual.posixpath
é o módulo subjacente que é usado em sistemas posix sob o namespaceos.path
:Assim, você pode apenas importar e usar
posixpath.join
para urls, que estão disponíveis e funcionarão em qualquer plataforma .Editar: a sugestão de @Pete é boa, você pode criar um alias para a importação para maior legibilidade
Edit: Eu acho que isso fica mais claro, ou pelo menos me ajudou a entender, se você olhar para a fonte de
os.py
(o código aqui é do Python 2.7.11, além disso, cortei alguns bits). Há importações condicionaisos.py
que selecionam qual módulo de caminho usar no namespaceos.path
. Todos os módulos subjacentes (posixpath
,ntpath
,os2emxpath
,riscospath
) que podem ser importados emos.py
, alias comopath
, estão lá e existem para ser utilizado em todos os sistemas.os.py
é apenas escolher um dos módulos para usar no namespaceos.path
em tempo de execução com base no sistema operacional atual.fonte
from posixpath import join as urljoin
agradavelmente aliases para algo fácil de ler.Isso faz o trabalho muito bem:
fonte
A função basejoin no pacote urllib pode ser o que você está procurando.
Edit: Eu não percebi antes, mas urllib.basejoin parece mapear diretamente para urlparse.urljoin, tornando o último preferido.
fonte
Usando furl,
pip install furl
será:fonte
.url
no final:furl.furl('/media/path/').add(path='js/foo.js').url
furl('/media/path/').add(path=furl('/js/foo.js').path).url
porquefurl('/media/path/').add(path='/js/foo.js').url
é/media/path//js/foo.js
Eu sei que isso é um pouco mais do que o OP pediu, mas eu tinha as peças para a seguinte url e estava procurando uma maneira simples de juntá-las:
Olhando ao redor:
Portanto, além do caminho de junção que já foi respondido nas outras respostas, Para conseguir o que procurava fiz o seguinte:
De acordo com a documentação , leva EXATAMENTE uma tupla de 5 partes.
Com o seguinte formato de tupla:
fonte
Rune Kaagaard forneceu uma solução excelente e compacta que funcionou para mim, eu a expandi um pouco:
Isso permite que todos os argumentos sejam unidos, independentemente das barras finais e finais, preservando a última barra, se houver.
fonte
return "/".join([str(x).strip("/") for x in args]) + trailing_slash
Para melhorar um pouco a resposta de Alex Martelli, o seguinte não apenas limpará barras extras, mas também preservará barras finais (finais), que às vezes podem ser úteis:
No entanto, não é tão fácil de ler e não limpará várias barras extras.
fonte
Descobri coisas que não gostei em todas as soluções acima, então criei a minha própria. Esta versão garante que as peças sejam unidas com uma única barra e deixa apenas as barras iniciais e finais. Não
pip install
, semurllib.parse.urljoin
estranheza.fonte
Usando furl e regex (python 3)
fonte