python - 在 Python 3 中,如何转换文件 ://URL to an OS path with code that works in both Linux and Windows?

标签 python file url path

以下代码演示了将 file://URL 转换为操作系统路径时出现的问题。

import os
import pathlib
import sys
import urllib.parse

print ("sys.argv[0]      = {0}".format(sys.argv[0]))

varFilename = sys.argv[0]
varFilename = os.path.abspath(varFilename)
print ("abs varFilename  = {0}".format(varFilename))

varMainFolder = os.path.dirname(varFilename)
print ("varMainFolder    = {0}".format(varMainFolder))

varTarget = os.path.join(varMainFolder,"test test.py")
print ("varTarget        = {0}".format(varTarget))

varURL = pathlib.Path(varTarget).as_uri()
print ("varURL           = {0}".format(varURL))

varPathRaw = urllib.parse.urlparse(varURL).path
print ("varPathRaw       = {0}".format(varPathRaw))

varPathDecode = urllib.parse.unquote(varPathRaw)
print ("varPathDecode    = {0}".format(varPathDecode))

varOSPath = os.path.normpath(varPathDecode)
print ("varOSPath        = {0}".format(varOSPath))

在 Linux 中,这段代码打印:

sys.argv[0]      = test.py
abs varFilename  = /home/ldbader/test.py
varMainFolder    = /home/ldbader
varTarget        = /home/ldbader/test test.py
varURL           = file:///home/ldbader/test%20test.py
varPathRaw       = /home/ldbader/test%20test.py
varPathDecode    = /home/ldbader/test test.py
varOSPath        = /home/ldbader/test test.py

注意 varOSPath 是一个完全有效的绝对路径。但在 Windows 中,代码打印:

sys.argv[0]      = test.py
abs varFilename  = C:\mli\Junk\test.py
varMainFolder    = C:\mli\Junk
varTarget        = C:\mli\Junk\test test.py
varURL           = file:///C:/mli/Junk/test%20test.py
varPathRaw       = /C:/mli/Junk/test%20test.py
varPathDecode    = /C:/mli/Junk/test test.py
varOSPath        = \C:\mli\Junk\test test.py

注意 varOSPath 有一个绝对路径,前面有一个无效的反斜杠。尝试使用此路径打开文件将失败。我原以为 os.path.normpath() 会丢弃驱动器规范左侧的斜线,但事实并非如此。

我应该怎么做才能使相同的逻辑在两个平台上为我提供有效的绝对路径?

最佳答案

好吧,这就是我的答案。它似乎适用于我的场景,但我不确定如果 Linux 用户创建名为/C:(或任何其他看起来像 Windows 驱动器盘符的名称)的文件夹会发生什么。

import os
import pathlib
import sys
import urllib.parse

print ("sys.argv[0]      = {0}".format(sys.argv[0]))

varFilename = sys.argv[0]
varFilename = os.path.abspath(varFilename)
print ("abs varFilename  = {0}".format(varFilename))

varMainFolder = os.path.dirname(varFilename)
print ("varMainFolder    = {0}".format(varMainFolder))

varTarget = os.path.join(varMainFolder,"test test.py")
print ("varTarget        = {0}".format(varTarget))

varURL = pathlib.Path(varTarget).as_uri()
print ("varURL           = {0}".format(varURL))

varPathRaw = urllib.parse.urlparse(varURL).path
print ("varPathRaw       = {0}".format(varPathRaw))

varPathDecode = urllib.parse.unquote(varPathRaw)
print ("varPathDecode    = {0}".format(varPathDecode))

varOSPath = os.path.normpath(varPathDecode)
print ("varOSPath        = {0}".format(varOSPath))

varFixedPath = varOSPath
varDrive = os.path.splitdrive(varFixedPath[1:])[0]
print ("varDrive         = {0}".format(varDrive))
if varDrive:
    varFixedPath = varFixedPath[1:]
print ("varFixedPath     = {0}".format(varFixedPath))

技巧是在删除第一个字符后在绝对路径上使用 os.path.splitdrive()。对于 Windows 绝对路径,它将返回驱动器规范。对于 Linux 绝对路径,它将返回一个空字符串。如果驱动器规范是空字符串,则按原样使用绝对路径。如果驱动器规范不是空字符串,则从绝对路径中删除第一个字符并使用结果。

我仍然认为 os.path.normpath() 方法不应返回带有前导反斜杠的绝对 Windows 路径。

关于python - 在 Python 3 中,如何转换文件 ://URL to an OS path with code that works in both Linux and Windows?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43103640/

相关文章:

python - pandas.concat 中的列顺序

jquery - 使用 jQuery 或 Javascript 写入本地文件

java - 在Java中,如何从后到前迭代文本文件中的行

python - 打开 2 个文件并将它们分配给 Python 3 中的 2 个集合

java - 如何向后端服务器上的firebase动态链接添加参数?

Python 正则表达式从 url 中提取 vimeo id

python - 由于带有 discord.py 的 "BAD REQUEST",消息未发送

python - 绕过 Cloudflare Scrapeshield

python - (PYTHON) to_excel - 忽略 URL...255 个字符,因为它超过了 Excel 的 URLS 限制

file - 什么 SSIS 任务可用于从 HTTPS URL 下载文件?