【发布时间】:2020-07-29 20:21:56
【问题描述】:
为什么 os.walk() 返回的根元素显示 / 作为目录分隔符,而 os.sep (或 os.path.sep) 在Win10上显示\?
我只是想为文件夹中的一组文件创建完整路径,如下所示:
import os
base_folder = "c:/data/MA Maps"
for root, dirs, files in os.walk(base_folder):
for f in files:
if f.endswith(".png") and f.find("_N") != -1:
print(os.path.join(root, f))
print(os.path.sep)
这是我得到的输出:
c:/data/MA Maps\Map_of_Massachusetts_Nantucket_County.png
c:/data/MA Maps\Map_of_Massachusetts_Norfolk_County.png
\
我知道 python 的一些库函数(如 open()) 可以与混合路径分隔符一起使用(至少在 Windows 上),但依赖该 hack 确实不能在所有库中都得到信任.似乎从 os.walk() 和 os.path (.sep 或 .join()) 应根据所使用的操作系统产生一致的结果。谁能解释为什么会发生这种不一致?
附: - 我知道有一个更一致的库用于处理文件路径(以及许多其他文件操作),称为 pathlib,它是在 python 3.4 中引入的,它似乎确实修复了这些所有。如果您的代码在 3.4 或更高版本中使用,是否最好使用 pathlib 方法来解决此问题?但是,如果您的代码针对使用 3.4 之前的 python 的系统,那么解决此问题的最佳方法是什么?
下面是 pathlib 的一个很好的基本解释:Python 3 Quick Tip: The easy way to deal with file paths on Windows, Mac and Linux
这是我使用 pathlib 的代码和结果:
import os
from pathlib import Path
# All of this should work properly for any OS. I'm running Win10.
# You can even mix up the separators used (i.e."c:\data/MA Maps") and pathlib still
# returns the consistent result given below.
base_folder = "c:/data/MA Maps"
for root, dirs, files in os.walk(base_folder):
# This changes the root path provided to one using the current operating systems
# path separator (/ for Win10).
root_folder = Path(root)
for f in files:
if f.endswith(".png") and f.find("_N") != -1:
# The / operator, when used with a pathlib object, just concatenates the
# the path segments together using the current operating system path separator.
print(root_folder / f)
c:\data\MA Maps\Map_of_Massachusetts_Nantucket_County.png
c:\data\MA Maps\Map_of_Massachusetts_Norfolk_County.png
这甚至可以更简洁地使用 pathlib 和列表理解(每个操作系统正确处理所有路径分隔符):
from pathlib import Path
base_folder = "c:/data/MA Maps"
path = Path(base_folder)
files = [item for item in path.iterdir() if item.is_file() and
str(item).endswith(".png") and
(str(item).find("_N") != -1)]
for file in files:
print(file)
c:\data\MA Maps\Map_of_Massachusetts_Nantucket_County.png
c:\data\MA Maps\Map_of_Massachusetts_Norfolk_County.png
这是非常 Pythonic 的,至少我觉得它很容易阅读和理解。 .iterdir() 真的很强大,它使处理文件和目录相当容易,并且以跨平台的方式。你怎么看?
【问题讨论】:
-
"...这是在 python 3.4 中引入的,它似乎确实解决了所有这些问题.." – 如果 Python 维护人员意识到这个问题并且 是 会怎样您正在寻找的解决方案?
-
但这仍然使 os 和 path 不一致,至少据我所知 pathlib 并没有得到一致使用。大多数关于 Python 文件处理的培训只讨论使用操作系统和路径。
-
Windows 较晚出现,并为版权选择了不同的路径分隔符
\。但它保持了 POSIX 兼容性,还允许/作为路径分隔符。您使用带有/的硬编码起始目录,但该目录使用操作系统标准\遍历添加的子目录。您可以规范化,获取硬编码起始目录的绝对路径。 -
完全了解历史以及为什么存在 / 和 \ 的混合。但是不明白为什么 os 和 path 不能根据所使用的操作系统产生一致的结果。如图所示,pathlib 在幕后处理所有这些,并且始终提供具有正确结果的路径,而与所使用的操作系统无关。似乎 os 和 path 应该做同样的事情。
-
似乎 root (从 os.walk() 返回)应该根据当前操作系统返回正确分离的根文件夹(不管 base_folder 路径如何分离)。如果这样做,那么 root 和 os.path.sep 将始终保持一致,并且您将始终确保您的路径独立于操作系统。我认为这种对 os 的更改不应该导致现有代码出现问题(但我可能会遗漏一些东西)。
标签: python python-3.x os.walk os.path path-separator