Python path.join 不同平台结果不同

系统 1746 0

转载: https://www.polarxiong.com/archives/Python-os-path-join-产生的斜杠在Windows和Linux下的不同表现和解决方法.html

 

问题描述

我一直以为Python是隔离了操作系统的差异,同样的function在不同操作系统下会有一致的结果,直到前几天临时切换到Windows下发现有些Python代码跑不出来,才发现如 os.path.join() 这样的方法在不同操作系统下的表现是不一致的。

例如

Python

            
              import os.path

print(os.path.join('a', 'b', 'c'))
            
          

在Linux/macOS下会显示

            
              a/b/c
            
          

而在Windows下会显示

            
              a\b\c
            
          

os.path.join() 在Linux/macOS下会以斜杠( / )分隔路径,而在Windows下则会以反斜杠( \ )分隔路径

这种不一致的表现在遇到jinja2下include模板文件路径时就会由于jinja2只支持斜杠( / ),而在Windows下使用 os.path.join() 会出现反斜杠( \ ),而造成找不到模板文件错误,参考这个issue。

原因分析

这种内置标准库方法的不一致从哪来的?官方文档实际上早就有明显的暗示了。

os.path 的官方文档页面11.2. os.path — Common pathname manipulations — Python 3.7.0 documentation开始位置就提到源代码文件根据不同操作系统在三个不同文件中:

Source code: Lib/posixpath.py (for POSIX), Lib/ntpath.py (for Windows NT), and Lib/macpath.py (for Macintosh)

可见在安装Python时就会根据不同操作系统,仅使用对应操作系统类别的 os.path 模块。如果顺着源码去看,就会发现 os.path.join() 在Linux下是以斜杠( / )作为分隔符的,而在Windows下则是以反斜杠( \ )作为分隔符的。

Mac的一些细节

如果跟着看Macintosh操作系统对应的源码Lib/macpath.py的话,会很惊讶地发现Macintosh下不是以斜杠( / )也不是以反斜杠( \ ),而是以冒号( : )作为分隔符的,是不是很震惊:我的mac怎么可能是以冒号( : )为分隔符的?!

这其实是一个历史问题了,这里Lib/macpath.py仅应用到了2001发布的Mac OS X之前的Macintosh操作系统中,那时的Macintosh确实是用冒号( : )为分隔符的。而从2001年的Mac OS X开始,到2012年的OS X,再到2016年的macOS,都采用了遵循Unix的斜杠( / )分隔符,也就直接使用Linux的源码Lib/posixpath.py了。

为什么Windows要使用反斜杠( \

为什么Windows不使用斜杠( / ),而独树一帜使用反斜杠( \ )呢,专门为了为难程序员?

这其实也是个历史问题,归根到底还是因为Windows为了保持对DOS的兼容性,而DOS为什么要使用反斜杠( \ )就说来话长了,可以参考MSDN上的一篇博文:Why is the DOS path character ""? – Larry Osterman's WebLog。

解决方法

从上面的分析可以发现 os.path.join() 仅包含对应操作系统类型的实现,所以我们无法通过指定参数的形式生成诸如适用于Linux或Windows的路径,那么如何解决这一问题呢?这里以在Windows下生成Linux格式(斜杠( / )分隔符)路径为例来说明。

通过 str.replace()

这是一种简单直接的方法,直接把Windows下 os.path.join() 生成的反斜杠( \ )全部替换为斜杠( / ),如:

Python

            
              import os.path

result = os.path.join('a', 'b', 'c')
print(result)

result = result.replace('\\', '/')
print(result)
            
          

会得到

            
              a\b\c
a/b/c
            
          

通过 pathlib.PurePath.as_posix()

从Python 3.4开始可以通过 pathlib.PurePath.as_posix() 来生成斜杠( / )格式的路径,其实其实现原理和 str.replace() 并没有太大区别。例如:

Python

            
              import os.path
from pathlib import Path

result = os.path.join('a', 'b', 'c')
print(result)

result = Path(result).as_posix()
print(result)
            
          

会得到

            
              a\b\c
a/b/c
            
          

参考

  • 11.2. os.path — Common pathname manipulations — Python 3.7.0 documentation
  • 11.1. pathlib — Object-oriented filesystem paths — Python 3.7.0 documentation

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论