Python:os.path.join()產生的斜杠在Windows和Linux下的不同表現和解決方法
覺得有用的話,歡迎一起討論相互學習~
原文鏈接
https://www.polarxiong.com/archives/Python-os-path-join-產生的斜杠在Windows和Linux下的不同表現和解決方法.html#comments
問題描述
- 我一直以為Python是隔離了操作系統的差異,同樣的function在不同操作系統下會有一致的結果,直到前幾天臨時切換到Windows下發現有些Python代碼跑不出來,才發現如os.path.join()這樣的方法在不同操作系統下的表現是不一致的。
- 例如
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下則會以反斜杠(\)分隔路徑。
原因分析
- 這種內置標准庫方法的不一致從哪來的?官方文檔實際上早就有明顯的暗示了。
- 在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為什么要使用反斜杠(\)就說來話長了
解決方法
- 從上面的分析可以發現os.path.join()僅包含對應操作系統類型的實現,所以我們無法通過指定參數的形式生成諸如適用於Linux或Windows的路徑,那么如何解決這一問題呢?這里以在Windows下生成Linux格式(斜杠(/)分隔符)路徑為例來說明。
通過str.replace()
- 這是一種簡單直接的方法,直接把Windows下os.path.join()生成的反斜杠(\)全部替換為斜杠(/),如:
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()並沒有太大區別。例如:
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