Python實戰(zhàn)之手把手教你寫一個帶界面的照片按日期歸檔與清理工具
前言
為硬盤減負(fù)你是否也有這樣的煩惱:手機或相機的存儲卡滿了,里面的照片和視頻成千上萬,堆在一個文件夾里雜亂無章?想把它們備份到移動硬盤,卻發(fā)現(xiàn)手動按日期分類太累?備份完了又不敢輕易刪除源文件,怕萬一沒拷過去怎么辦?
今天,我們將利用 Python 和 wxPython 圖形界面庫,編寫一個自動化的工具。它不僅能按拍攝日期自動歸檔媒體文件,還能在校驗成功后安全地將源文件移入回收站。
核心功能與技術(shù)棧
我們要實現(xiàn)的功能非常明確:
- GUI 界面:通過日歷選擇日期,通過文件選擇器選擇源目錄和目標(biāo)目錄。
- 按日期篩選:自動掃描源文件夾(包括子目錄),找出指定日期創(chuàng)建的照片/視頻。
- 自動歸檔:在目標(biāo)盤建立 YYYYMMDD 格式的文件夾,并復(fù)制文件。
- 安全清理:復(fù)制成功且校驗無誤后,將源文件移入回收站(而不是直接永久刪除)。
- 防假死:使用多線程處理文件操作,防止界面卡頓。
使用的庫:
- wxPython: 繪制原生風(fēng)格的圖形界面。
- shutil: 負(fù)責(zé)文件的高級復(fù)制(保留元數(shù)據(jù))。
- os & datetime: 處理文件路徑和時間。
- send2trash: 關(guān)鍵庫,用于將文件發(fā)送到回收站。
- threading: 實現(xiàn)后臺任務(wù)處理。
代碼深度剖析
界面布局 (GUI Layout)
我們繼承了 wx.Frame 來創(chuàng)建主窗口。布局上使用了 wx.BoxSizer,這是一種彈性盒子布局,能夠讓界面元素隨窗口大小自動調(diào)整。
核心控件初始化
self.date_picker = wx.adv.DatePickerCtrl(panel, style=wx.adv.DP_DROPDOWN | wx.adv.DP_SHOWCENTURY) self.src_picker = wx.DirPickerCtrl(panel, message=“選擇源文件夾”) self.dst_picker = wx.DirPickerCtrl(panel, path=default_path, message=“選擇目標(biāo)文件夾”)
亮點:使用了 DatePickerCtrl,讓用戶點選日歷,而不是手動輸入“2023-11-25”,減少了格式錯誤的可能。
遇到的“坑”:wx.DateTime 類型轉(zhuǎn)換
在編寫過程中,我們遇到了一個典型的報錯:
TypeError: unsupported operand type(s) for +: ‘sip.enumtype’ and ‘int’
原因分析:wxPython 的較新版本(Phoenix)中,wx_date.Month 屬性返回的是一個枚舉對象(如 wx.DateTime.Month.Jan),而不是整數(shù)。且 wxPython 的月份是從 0 開始(0-11),而 Python 標(biāo)準(zhǔn)庫 datetime 需要的是 1-12。
解決方案:我們必須使用 .GetMonth() 方法獲取整數(shù)值,并手動 +1。
修正后的代碼
wx_date = self.date_picker.GetValue()
GetMonth() 返回 0-11,所以需要 +1
target_date = datetime.date(wx_date.GetYear(), wx_date.GetMonth() + 1, wx_date.GetDay())
核心邏輯:遍歷與篩選
為了找到深藏在子文件夾里的照片,我們使用了 os.walk()。它可以遞歸地遍歷目錄樹。
MEDIA_EXTENSIONS = {‘.jpg', ‘.mp4', …} # 定義白名單
for root, dirs, files in os.walk(src_dir):
for file in files:
# 1. 擴展名過濾
if ext.lower() not in MEDIA_EXTENSIONS: continue
# 2. 日期匹配
ctime = os.path.getctime(file_path)
file_date = datetime.date.fromtimestamp(ctime)
if file_date == target_date:
self.ProcessFile(...)
這里的邏輯非常嚴(yán)謹(jǐn):只處理白名單內(nèi)的媒體文件,避免誤移動系統(tǒng)文件或文本文件。
數(shù)據(jù)安全:復(fù)制與“后悔藥”機制
這是本工具最核心的價值所在。普通腳本用 shutil.move,一旦出錯文件可能丟失。我們采用了“復(fù)制+校驗+放入回收站”的三步走策略。
def ProcessFile(self, src_path, dst_folder, filename):
# … 省略重名處理 …
# 第一步:復(fù)制 (copy2 保留拍攝時間等元數(shù)據(jù))
shutil.copy2(src_path, dst_path)
# 第二步:校驗
# 確保目標(biāo)文件存在,且大小與源文件一致
if os.path.exists(dst_path) and os.path.getsize(dst_path) == os.path.getsize(src_path):
# 第三步:安全刪除 (放入回收站)
send2trash(src_path)
else:
self.Log("錯誤:復(fù)制校驗失敗,未刪除源文件")
使用 send2trash 是為了給用戶一劑“后悔藥”。萬一你選錯了日期或者程序邏輯有誤,文件只是在回收站里,隨時可以還原,數(shù)據(jù)安全大于一切。
用戶體驗:多線程防假死
如果直接在按鈕點擊事件里運行上述循環(huán),處理幾百個視頻時,界面會直接卡死(顯示“未響應(yīng)”)。為了解決這個問題,我們引入了 threading。
def OnStartBackup(self, event):
# 禁用按鈕
self.btn_start.Disable()
# 開啟子線程
thread = threading.Thread(target=self.RunBackupLogic, args=(…))
thread.start()
def Log(self, message):
# 使用 wx.CallAfter 確保在主線程更新 UI,防止崩潰
wx.CallAfter(self.log_ctrl.AppendText, f"…{message}\n")注意:子線程不能直接操作界面控件(如 TextCtrl),必須使用 wx.CallAfter 將更新指令發(fā)送回主UI線程,這是 GUI 編程的金科玉律。
運行效果
程序啟動后,只需三步:
- 選擇你要整理的那一天的日期(例如某次旅游的日期)。
- 選擇存放混亂照片的源文件夾。
- 選擇移動硬盤作為目標(biāo)文件夾。
點擊“開始”,你會在日志框看到一行行滾動的記錄:
[10:00:01] 成功備份并清理: IMG_2023.JPG
[10:00:02] 發(fā)現(xiàn)重名,重命名為: VIDEO_001_1.MP4
完成后,程序目錄還會生成一個 backup_history.txt,記錄你的備份流水。
運行結(jié)果



到此這篇關(guān)于Python實戰(zhàn)之手把手教你寫一個帶界面的照片按日期歸檔與清理工具的文章就介紹到這了,更多相關(guān)Python文件按日期歸檔內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Python的Twisted框架編寫簡單的網(wǎng)絡(luò)客戶端
這篇文章主要介紹了使用Python的Twisted框架編寫簡單的網(wǎng)絡(luò)客戶端,翻譯自Twisted文檔,包括一個簡單的IRC客戶端的實現(xiàn),需要的朋友可以參考下2015-04-04
解決Pytorch中的神坑:關(guān)于model.eval的問題
這篇文章主要介紹了解決Pytorch中的神坑:關(guān)于model.eval的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05
使用Python構(gòu)建MCP服務(wù)器的詳細(xì)配置步驟
模型控制協(xié)議(MCP)是一種專為實現(xiàn)AI代理與工具解耦而設(shè)計的通信協(xié)議,為AI驅(qū)動應(yīng)用程序的開發(fā)提供了高度的靈活性和模塊化架構(gòu),本文將詳細(xì)介紹MCP服務(wù)器的構(gòu)建過程,包括工具函數(shù)的注冊、配置以及與Claude Desktop等AI代理的集成,需要的朋友可以參考下2025-06-06
pytest實戰(zhàn)技巧之參數(shù)化基本用法和多種方式
本文介紹了pytest參數(shù)化的基本用法和多種方式,幫助讀者更好地使用這個功能,同時,還介紹了一些高級技巧,如動態(tài)生成參數(shù)名稱、參數(shù)化的組合和動態(tài)生成參數(shù)化裝飾器,幫助讀者更靈活地使用參數(shù)化,感興趣的朋友參考下吧2023-12-12

