歡迎光臨
每天分享高質量文章

Windows檔案名非用反斜杠?Python小技巧幫你解決這個麻煩

(點擊上方公眾號,可快速關註一起學Python)

來自:機器之心    作者:Adam Geitgey

參與:Geek AI、張倩

要想讓你的 Python 代碼同時在 Windows 和 Mac/Linux 上工作,你需要處理不同系統檔案名用不同斜杠的問題。而 Python 3 有一個名為「pathlib」的新模塊,可以幫你解決這個麻煩。

在編程過程中,我們往往會遇到一個小麻煩——微軟 Windows 系統在檔案夾名之間使用反斜杠字符,而幾乎所有其它的計算機(操作系統)都使用正斜杠:

Windows filenames:
C:\some_folder\some_file.txt

Most other operating systems:
/some_folder/some_file.txt

這是由於上世紀 80 年代早期計算機歷史上的一個小意外。「MS-DOS」的第一版使用了正斜杠字符來指定命令列選項。當微軟在「MS-DOS 2.0」中加入了對檔案夾的支持時,正斜杠字符已經被使用了,所以他們採用了反斜杠作為替代。35 年後,我們仍然被受困於這種不一致性。

如果你想讓你的 Python 代碼同時在 Windows 和 Mac/Linux 上工作,你就需要處理這種與平臺相關的問題。幸運的是,Python 3 有一個名為「pathlib」的新模塊,使得用戶處理檔案幾乎沒有任何困難。

「pathlib」模塊鏈接:https://docs.python.org/3/library/pathlib.html

讓我們快速瀏覽一下處理檔案名路徑的不同方法,看看「pathlib」如何能讓你的生活變得更美好!

錯誤的解決方案:手動構建檔案路徑

假設你有一個資料檔案夾,該檔案夾包含你想要在你的 Python 程式中打開的檔案:

在 Python 中對其進行編碼是「錯誤」的方式:

data_folder = "source_data/text_files/"

file_to_open = data_folder + "raw_data.txt"

f = open(file_to_open)

print(f.read())

請註意,由於我使用的是 Mac 系統,所以我使用了「Unix」風格的正斜杠對路徑進行了硬編碼。這也會讓 Windows 的用戶感到憤怒。

從技術上講,這段代碼在 Windows 上仍然有效,因為 Python 有一個「黑客」(hack)技術:當你在 Windows 上呼叫「open()」函式時,它會識別這兩種斜線。但即便如此,你也不應該依賴它。如果你在錯誤的操作系統上使用了錯誤型別的斜杠(尤其是在它們與外部程式或代碼庫交互時),並不是所有的 Python 庫都會正常工作。

Python 對混合斜杠型別的支持是一種只針對 Windows 的「黑客」技術,它反過來並不起作用。在 Mac 系統環境下,在代碼中使用反斜杠會導致徹底失敗:

data_folder = "source_data\\text_files\\"

file_to_open = data_folder + "raw_data.txt"

f = open(file_to_open)

print(f.read())

# On a Mac, this code will throw an exception:
# FileNotFoundError: [Errno 2] No such file or directory: 'source_data\\text_files\\raw_data.txt'

由於所有這些原因以及其他原因,使用硬編碼的路徑字串編寫代碼,是一種會讓其他程式員十分「嫌棄」的做法。一般來說,你應該儘量避免這麼做。

以前的解決方案:Python 的「os.path」模塊

Python 的「os.path」模塊有很多工具來處理這類針對特定操作系統的檔案系統問題。

你可以使用「os.path.join()」為當前的操作系統構建一個使用正確型別斜杠的路徑字串:

import os.path

data_folder = os.path.join("source_data""text_files")

file_to_open = os.path.join(data_folder, "raw_data.txt")

f = open(file_to_open)

print(f.read())

這段代碼可以同時在「Windows」或「Mac」系統上完美運行。問題是它使用起來很麻煩。寫出「os.path.join()」並將路徑的每個部分作為獨立的字串傳給該函式非常冗長,而且很不直觀。

由於「os.path」模塊中的大多數函式使用起來很煩人,開發者們通常會「忘記」使用它們,即使他們知道這樣做更好。這導致出現了很多跨平臺的 Bug,也引起了用戶的憤怒。

更好的解決方案:Python 3 的「pathlib」!

為了處理檔案和路徑,Python 3.4 引入了一個名為「pathlib」的新標準庫,而且非常好用!

要使用該庫,你只需使用正斜杠將一個路徑或檔案名傳給一個新的「Path()」物件,然後它將處理餘下的操作:

from pathlib import Path

data_folder = Path("source_data/text_files/")

file_to_open = data_folder / "raw_data.txt"

f = open(file_to_open)

print(f.read())

在這裡,有兩點需要註意:

  • 你應該在使用「pathlib」函式的情況下使用正斜杠。「Path()」函式將會把正斜杠轉化為適應當前操作系統環境的正確斜杠。贊!

  • 如果你想要在路徑上進行添加,你可以直接在你的代碼中使用「/」運算子。你再也不用一遍又一遍地輸入「os.path.join(a, b)」了。

如果「pathlib」所做的就這麼多,它也已經是對於 Python 的一個很好的補充了。但是,它還能做更多!

例如,我們可以在無需打開和關閉檔案的情況下,讀取文本檔案的內容:

from pathlib import Path

data_folder = Path("source_data/text_files/")

file_to_open = data_folder / "raw_data.txt"

print(file_to_open.read_text())

專業提示:之前的示例是有 Bug 的,因為打開的檔案從來沒有被關閉過。而這裡的這種語法則徹底避免了這個 Bug。

事實上,「pathlib」使大多數標準的檔案操作變得快速而簡單:

from pathlib import Path

filename = Path("source_data/text_files/raw_data.txt")

print(filename.name)
# prints "raw_data.txt"

print(filename.suffix)
# prints "txt"

print(filename.stem)
# prints "raw_data"

if not filename.exists():
    print("Oops, file doesn't exist!")
else:
    print("Yay, the file exists!")

你甚至可以使用「pathlib」顯式地將一個「Unix」路徑轉化為一個「Windows」格式的路徑:

from pathlib import Path, PureWindowsPath

filename = Path("source_data/text_files/raw_data.txt")

# Convert path to Windows format
path_on_windows = PureWindowsPath(filename)

print(path_on_windows)
# prints "source_data\text_files\raw_data.txt"

如果你真的想安全地在你的代碼中使用反斜杠,你可以按照「Windows」格式宣告你的路徑,而「pathlib」可以對其進行轉化,使其能在當前的操作系統中工作:

from pathlib import Path, PureWindowsPath

# I've explicitly declared my path as being in Windows format, so I can use forward slashes in it.
filename = PureWindowsPath("source_data\\text_files\\raw_data.txt")

# Convert path to the right format for the current operating system
correct_path = Path(filename)

print(correct_path)
# prints "source_data/text_files/raw_data.txt" on Mac and Linux
# prints "source_data\text_files\raw_data.txt" on Windows

如果你想把代碼寫得更「高級」一些,你甚至可以使用「pathlib」來做諸如解析相對路徑、解析網絡共享路徑並生成「file:// urls」之類的事。在下麵的例子中,我們將僅僅使用兩行代碼,在你的 web 瀏覽器中打開一個本地檔案夾:

from pathlib import Path
import webbrowser

filename = Path("source_data/text_files/raw_data.txt")

webbrowser.open(filename.absolute().as_uri())

這隻是「pathlib」的好處之一。它很好地替代了過去分散在不同 Python 模塊中與檔案相關的許多不同功能。

已同步到看一看
赞(0)

分享創造快樂