Windows 文件方案 URI 上的 urlparse() 在开始时留下额外的斜线

S. *_*rby 3 python windows uri

我正在制作一个需要从拖放输入中读取 URI 的应用程序。我正在尝试使用urllib.parse.urlparse().

urlparse() 按预期处理 Internet URL:

>>> import urllib
>>> urllib.parse.urlparse('https://www.google.com/advanced_search')
ParseResult(scheme='https', netloc='www.google.com', path='/advanced_search', params='', query='', fragment='')
Run Code Online (Sandbox Code Playgroud)

但是在本地 Windows 文件上使用它会在路径的开头留下一个额外的斜线:

>>> urllib.parse.urlparse('file:///C:/Program%20Files/Python36/LICENSE.txt')
ParseResult(scheme='file', netloc='', path='/C:/Program%20Files/Python36/LICENSE.txt', params='', query='', fragment='')
Run Code Online (Sandbox Code Playgroud)

事实上,需要本地文件路径的函数似乎不喜欢这个额外的斜杠:

>>> from pathlib import Path
>>> Path('/C:/Program%20Files/Python36/LICENSE.txt').exists()
Traceback (most recent call last):
...
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: '\\C:\\Program%20Files\\Python36\\LICENSE.txt'
Run Code Online (Sandbox Code Playgroud)

我可以编写一个我自己的特殊情况来以file:///<Windows drive letter>:某种方式处理,但作为一个清洁问题:是否有更好的 Python 函数来分割 URI,而不仅仅是 URL?或者还有什么我想念的吗?

使用 Python 3.6.1。

S. *_*rby 5

使用urllib.request.url2pathname()路径组件将剥离的Windows开始斜线。

>>> import urllib
>>> import urllib.request
>>> path = urllib.parse.urlparse('file:///C:/Program%20Files/Python36/LICENSE.txt').path
>>> path
'/C:/Program%20Files/Python36/LICENSE.txt'
>>> urllib.request.url2pathname(path)
'C:\\Program Files\\Python36\\LICENSE.txt'
Run Code Online (Sandbox Code Playgroud)

因此,url2pathname()如果urlparse()结果的方案是file.


感谢@eryksun 的评论,指出pip 使用url2pathname(). pip 还展示了如何更多地概括代码以处理 Windows UNC 路径,这些路径用于 Windows 共享网络文件夹等。如果方案是'file'并且 netloc 非空,则似乎可以检测到 UNC 路径,我们需要在使用 UNC 路径之前添加几个反斜杠。

>>> parse_result = urllib.parse.urlparse('file://some-host/Shared Travel Photos/20170312_112803.jpg')
>>> parse_result
ParseResult(scheme='file', netloc='some-host', path='/Shared Travel Photos/20170312_112803.jpg', params='', query='', fragment='')
>>> urllib.request.url2pathname(r'\\' + parse_result.netloc + parse_result.path)
'\\\\some-host\\Shared Travel Photos\\20170312_112803.jpg'
Run Code Online (Sandbox Code Playgroud)