檔案操作前的存在性檢查是防錯第一道防線。Python 提供 os.path 系列函數,但行為細節(符號連結、權限、遠端協議)常被忽略。本文系統整理 8 種檢查場景與最佳實踐。
| 函數 | 用途 | 回傳值 | 符號連結行為 |
|---|---|---|---|
os.path.exists(path) | 路徑存在(檔案/目錄/連結) | True/False | 跟隨連結檢查目標 |
os.path.isfile(path) | 是一般檔案 | True/False | 跟隨連結檢查目標 |
os.path.isdir(path) | 是目錄 | True/False | 跟隨連結檢查目標 |
os.path.lexists(path) | 路徑存在(含壞掉的連結) | True/False | 不跟隨連結,連結本身存在即 True |
import os
path_dir = 'd:/assist'
path_file = 'd:/assist/getTeacherList.py'
print(os.path.exists(path_dir)) # True
print(os.path.exists(path_file)) # True
print(os.path.isfile(path_dir)) # False
print(os.path.isfile(path_file)) # True
# 建立多層目錄
os.makedirs('d:/assist/set', exist_ok=True)
print(os.path.exists('d:/assist/set')) # True
from os import path, access, R_OK
FILE = './data.txt'
if path.exists(FILE) and path.isfile(FILE) and access(FILE, R_OK):
print("檔案存在且可讀")
else:
print("檔案缺失或不可讀")
def file_exists(filename):
try:
with open(filename) as f:
return True
except IOError:
return False
優點:避免 TOCTOU(檢查時與使用時狀態不一致)競態條件,碼風符合 Python「請求寬恕而非許可」哲學。
# 建立指向不存在目標的連結
os.symlink('/not/exist', 'broken_link')
print(os.path.exists('broken_link')) # False(目標不存在)
print(os.path.lexists('broken_link')) # True(連結本身存在)
from ftplib import FTP, error_perm
ftp = FTP('ftp.example.com')
ftp.login('user', 'pass')
# 方法一:嘗試下載,捕獲權限錯誤
def ftp_file_exists(ftp, filename):
try:
ftp.voidcmd(f'SIZE {filename}') # 僅查大小,不下載
return True
except error_perm:
return False
# 方法二:列出目錄內容比對
def ftp_dir_exists(ftp, dirname):
try:
ftp.cwd(dirname) # 嘗試切換
ftp.cwd('..') # 切回
return True
except error_perm:
return False
# 方法三:MLSD 指令(現代 FTP 伺服器支援)
def ftp_list(ftp, path):
try:
return [entry for entry in ftp.mlsd(path)]
except error_perm:
return []
os.path.exists('') 回傳 False,但 open('') 會拋出異常access() 檢查的是實際 UID/GID 權限,而非 effective 權限(setuid 程式需注意)pathlib.Path 物件導向介面:
from pathlib import Path
p = Path('data.txt')
p.exists(), p.is_file(), p.is_dir(), p.is_symlink()
選對檢查方式,能讓檔案操作更健壯、更符合 Python 風格。