Por ejemplo, quiero unir una ruta de prefijo a rutas de recursos como /js/foo.js.
Quiero que la ruta resultante sea relativa a la raíz del servidor. En el ejemplo anterior, si el prefijo era "media", me gustaría que el resultado fuera /media/js/foo.js.
os.path.join hace esto muy bien, pero la forma en que une las rutas depende del sistema operativo. En este caso, sé que estoy apuntando a la web, no al sistema de archivos local.
¿Existe una mejor alternativa cuando trabaja con rutas que sabe que se utilizarán en las URL? ¿Os.path.join funcionará lo suficientemente bien? ¿Debería enrollar el mío?
os.path.join
no trabajará. Pero simplemente unirse por el/
carácter debería funcionar en todos los casos:/
es el separador de ruta estándar en HTTP según la especificación.Respuestas:
Dado que, a partir de los comentarios que publicó el OP, parece que no quiere conservar "URL absolutas" en la unión (que es uno de los trabajos clave de
urlparse.urljoin
;-), recomiendo evitarlo.os.path.join
también sería malo, exactamente por la misma razón.Entonces, usaría algo como
'/'.join(s.strip('/') for s in pieces)
(si el encabezado/
también debe ignorarse, si el encabezado debe tener una carcasa especial, eso también es factible, por supuesto ;-).fuente
os.path.join('http://media.com', 'content')
volveráhttp://media.com\content
.Puede utilizar
urllib.parse.urljoin
:Pero cuidado :
La razón por la que obtienes resultados diferentes de
/js/foo.js
yjs/foo.js
es porque el primero comienza con una barra que significa que ya comienza en la raíz del sitio web.En Python 2, tienes que hacer
fuente
urljoin
alguna vez elimine '/'. Si lo llamo conurlparse.urljoin('/media/', '/js/foo.js')
el valor devuelto es '/js/foo.js'. Eliminó todos los medios, no el duplicado '/'. De hecho, enurlparse.urljoin('/media//', 'js/foo.js')
realidad devuelve '/media//js/foo.js', por lo que no se eliminan los duplicados.urljoin
no es para unirse a URL. Es para resolver URL relativas como se encuentran en documentos HTML, etc.Como dices,
os.path.join
une rutas basadas en el sistema operativo actual.posixpath
es el módulo subyacente que se utiliza en los sistemas posix bajo el espacio de nombresos.path
:Por lo tanto, puede importar y usar
posixpath.join
en su lugar las URL, que están disponibles y funcionarán en cualquier plataforma .Editar: la sugerencia de @ Pete es buena, puede alias de la importación para una mayor legibilidad
Editar: Creo que esto queda más claro, o al menos me ayudó a entender, si miras la fuente de
os.py
(el código aquí es de Python 2.7.11, además he recortado algunos bits). Hay importaciones condicionalesos.py
que eligen qué módulo de ruta usar en el espacio de nombresos.path
. Todos los módulos subyacentes (posixpath
,ntpath
,os2emxpath
,riscospath
) que pueden ser importados enos.py
, alias comopath
, hay y existen para ser utilizado en todos los sistemas.os.py
es simplemente elegir uno de los módulos para usar en el espacioos.path
de nombres en tiempo de ejecución según el sistema operativo actual.fuente
from posixpath import join as urljoin
muy bien lo alias a algo fácil de leer.Esto hace bien el trabajo:
fuente
La función basejoin en el paquete urllib podría ser lo que está buscando.
Editar: no me di cuenta antes, pero urllib.basejoin parece mapear directamente a urlparse.urljoin, lo que hace que este último sea el preferido.
fuente
Usando furl,
pip install furl
será:fuente
.url
al 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
es/media/path//js/foo.js
Sé que esto es un poco más de lo que pidió el OP, sin embargo, tenía las piezas para la siguiente URL y estaba buscando una forma sencilla de unirme a ellas:
Mirando alrededor:
Entonces, además de la ruta de unión que ya se ha respondido en las otras respuestas, para obtener lo que estaba buscando, hice lo siguiente:
Según la documentación, se necesita EXACTAMENTE una tupla de 5 partes.
Con el siguiente formato de tupla:
fuente
Rune Kaagaard proporcionó una solución excelente y compacta que funcionó para mí, la amplié un poco:
Esto permite que todos los argumentos se unan independientemente de las barras al final y al final mientras se conserva la última barra si está presente.
fuente
return "/".join([str(x).strip("/") for x in args]) + trailing_slash
Para mejorar ligeramente la respuesta de Alex Martelli, lo siguiente no solo limpiará las barras adicionales, sino que también conservará las barras finales (finales), que a veces pueden ser útiles:
Sin embargo, no es tan fácil de leer y no limpiará varias barras finales adicionales.
fuente
Encontré cosas que no me gustaron de todas las soluciones anteriores, así que se me ocurrió la mía. Esta versión asegura que las partes se unan con una sola barra y deja las barras al principio y al final solas. No
pip install
, sinurllib.parse.urljoin
rarezas.fuente
Usando furl y regex (python 3)
fuente