【问题标题】:Convert a filename to a file:// URL将文件名转换为 file:// URL
【发布时间】:2012-07-26 02:42:26
【问题描述】:

在 WeasyPrint 的公共 API 中,我接受 HTML 输入的文件名(以及其他类型)。任何与内置 open() 一起使用的文件名都应该可以使用,但我需要将其转换为 file:// 方案中的 URL,稍后将传递给 urllib.urlopen()

(内部的一切都是 URL 形式。我需要有一个文档的“基本 URL”,以便使用 urlparse.urljoin() 解析相对 URL 引用。)

urllib.pathname2url 是一个开始:

将路径名路径从路径的本地语法转换为 URL 的路径组件中使用的形式。 这不会产生完整的 URL。返回值已经使用 quote() 函数引用。

重点是我的,但我确实需要一个完整的 URL。到目前为止,这似乎有效:

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)

RFC 3987 (IRI) 似乎推荐使用 UTF-8。但在这种情况下(URL 最终是用于 urllib)也许我应该使用sys.getfilesystemencoding()

但是,基于the literature,我应该不只是在file: 前面加上file:// ...除非我不应该:在Windows 上,nturl2path.pathname2url() 的结果已经以三个斜杠开头。

所以问题是:有没有更好的方法来做到这一点并使其跨平台?

【问题讨论】:

  • 您不能只检查url[0:2] == '///' 之类的内容,如果为假,则添加两个额外的斜线吗?
  • 约阿希姆,也许这行得通。我只是不知道要遵循什么规则来避免令人惊讶的极端情况。
  • 嘿,您的示例代码使用了urlparse.pathname2url,它不存在。你的意思是urllib.pathname2url

标签: python url filenames


【解决方案1】:

感谢上述@danodonovan 的评论。

对于 Python3,以下代码将起作用:

from urllib.parse import urljoin
from urllib.request import pathname2url

def path2url(path):
    return urljoin('file:', pathname2url(path))

【讨论】:

    【解决方案2】:

    为了完整起见,在 Python 3.4+ 中,您应该这样做:

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

    【讨论】:

    • 这个模块也在 PyPI 上(对于其他 Python 版本)pypi.python.org/pypi/pathlib
    • pathlib2 现在应该用于其他 Python 版本
    • as_uri() 不适用于相对文件名(存在仅将部分文件名转换为(部分)URL 的用例
    【解决方案3】:

    我不确定文档是否足够严格以保证这一点,但我认为这在实践中有效:

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

    【讨论】:

    • 在 Linux、Windows 和 OS X 上测试过,并且在这三者上都可以正常工作。
    • 而在 py3k 中,这变成了 import urlib.parse as urlparseimport urlib.request as urllib
    • 您应该在这里致电os.path.abspath(path)
    • 如果您使用 six 库来确保 Python 2 和 3 的可移植性:return six.moves.urllib_parse.urljoin( "file://", six.moves.urllib.request.pathname2url(path))
    • 这会产生看起来像file:///C:/foo%20bar/spam/eggs" 的url 不应该是file:///C%3A/foo%20bar/spam/eggs",冒号变成%3A
    【解决方案4】:

    以下内容对您有用吗?

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

    【讨论】:

    • 这个想法很有趣,但我不知道这是否足够。特别是,` in Windows filenames is supposed to become /. Still on Windows, The C in C:\foo\bar.html` 被解析为一个方案,然后被替换。预期输出为file:///C:/foo/bar.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 2011-05-24
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    相关资源
    最近更新 更多