Convertir un nombre de archivo en un archivo: // URL

En la API pública de WeasyPrint, acepto nombres de archivo (entre otros tipos) para las entradas HTML. Cualquier nombre de archivo que funcione con el open() incorporado debería funcionar, pero debo convertirlo en una URL en el esquema file:// que luego se urllib.urlopen() a urllib.urlopen() .

(Todo está en forma de URL internamente. Necesito tener una “URL base” para los documentos a fin de resolver las referencias relativas a las URL con urlparse.urljoin() .)

urllib.pathname2url es un comienzo:

Convierta la ruta de acceso de la ruta desde la syntax local para una ruta al formulario utilizado en el componente de ruta de una URL. Esto no produce una URL completa. El valor de retorno ya se cotizará utilizando la función quote ().

El énfasis es mío, pero necesito una URL completa. Hasta ahora esto parece funcionar:

 def path2url(path): """Return file:// URL from a filename.""" path = os.path.abspath(path) if isinstance(path, unicode): path = path.encode('utf8') return 'file:' + urlparse.pathname2url(path) 

UTF-8 parece ser recomendado por RFC 3987 (IRI) . Pero en este caso (la URL está destinada a urllib, eventualmente) ¿quizás debería usar sys.getfilesystemencoding () ?

Sin embargo, de acuerdo con la literatura , debería añadir no solo el file: sino el file:// … excepto cuando no debería: en Windows, los resultados de nturl2path.pathname2url() ya comienzan con tres barras diagonales.

Entonces la pregunta es: ¿hay una mejor manera de hacer esto y hacerlo multiplataforma?

Para completar, en Python 3.4+, debes hacer:

 import pathlib pathlib.Path(absolute_path_string).as_uri() 

No estoy seguro de que los documentos sean lo suficientemente rigurosos como para garantizarlo, pero creo que esto funciona en la práctica:

 import urlparse, urllib def path2url(path): return urlparse.urljoin( 'file:', urllib.pathname2url(path)) 

Crédito para comentar desde @danodonovan arriba.

Para Python3, el siguiente código funcionará:

 from urllib.parse import urljoin from urllib.request import pathname2url def path2url(path): return urljoin('file:', pathname2url(path)) 

¿Funciona lo siguiente para ti?

 from urlparse import urlparse, urlunparse urlunparse(urlparse('yourURL')._replace(scheme='file'))