寫在前面的話
詩經有云:五月斯螽動股,六月莎雞振羽,七月在野,八月在宇,九月在戶,十月蟋蟀入我牀下。十一月有點涼,十二月被窩到不了的地方都是遠方。這句話的意思就是:五月蚱蜢彈腿跳,六月紡織娘振翅,七月蟋蟀在田野,八月來到屋檐下,九月蟋蟀進門口,十月鑽進我牀下。十一月天氣有點涼,十二月被窩到不了的地方都是遠方。
既然天氣這麼冷,不想去遠方,不如搞點事情吧~ 前幾天因爲工作關係,需要遠程其他地方的電腦,爲了方便,下載了某遠程工具,結果自動安裝上了一堆的流氓軟件,其中就有一個壓縮軟件,天天推送一些不知所云的廣告,讓我花費了很大的力氣才徹底清除。我在想能不能用Python自己實現一個壓縮軟件,這樣自己用的也方便,也不怕有什麼廣告了,我們的故事便從這裏開始……
一、相關庫簡介
(1)zipfile庫
首先我想到了Python中有一個實現解壓縮的很方便的庫——zipfile庫。zipfile用來做zip格式編碼的壓縮和解壓縮,由於是很常見的zip格式,所以這個模塊使用頻率也是比較高。它有兩個非常重要的class,分別是ZipFile和ZipInfo, 在絕大多數的情況下,只需要使用這兩個class就可以。ZipFile是主要的類,用來創建和讀取zip文件;ZipInfo是存儲的zip文件的每個文件的信息的。
(2)os庫
Python的os模塊提供了簡單方便的方法來使用操作系統的一些功能。就是說通過os庫可以使用python執行一些常見的操作系統的功能,比如切換目錄,增刪文件,設置環境變量,運行shell 命令等等。以下是os庫常用的部分:
os.sep:可以取代操作系統特定的路徑分隔符。
os.name:字符串指示你正在使用的平臺。比如對於Windows,它是'nt',而對於Linux/Unix用戶,它是'posix'。
os.getcwd():函數得到當前工作目錄,即當前Python腳本工作的目錄路徑。
os.getenv():獲取一個環境變量,如果沒有返回none。
os.link():方法用於創建硬鏈接。
os.mkdir():方法用於以數字權限模式創建目錄。
os.listdir(path):返回指定目錄下的所有文件和目錄名。
os.remove(path):函數用來刪除一個文件。如果指定的路徑是一個目錄,將拋出OSError,在Unix,Windows中有效。
os.rmdir(path):方法用於刪除指定路徑的目錄。僅當這文件夾是空的纔可以,否則,拋出OSError。
os.system(command):函數用來運行shell命令。
os.linesep:字符串給出當前平臺使用的行終止符。
os.curdir:返回當前目錄('.')。
os.chdir(dirname):改變工作目錄到dirname。
os.path常用方法:
os.path.isfile(path)和os.path.isdir(path)函數:分別檢驗給出的路徑是一個文件還是目錄,絕對路徑。
os.path.existe():函數用來檢驗給出的路徑是否真地存在。
os.path.getsize(name):獲得文件大小。
os.path.abspath(name):獲得絕對路徑。
os.path.normpath(path):規範path字符串形式。
os.path.split(path):將path分割成目錄和文件名二元組返回。
os.path.splitext():分離文件名與擴展名。
os.path.join(path,name):連接目錄與文件名或目錄;使用“\”連接。
os.path.basename(path):返回文件名。
os.path.dirname(path):返回文件路徑。
(3)Tkinter組件
Tkinter提供的各種控件如下圖所示:
Tkinter組件的標準屬性(所有控件均有的屬性)如下所示:
Tkinter控件有特定的幾何狀態管理方法,管理整個控件區域組織,以下是Tkinter公開的幾何管理類:包、網格、位置。
二、相關方法編寫
1、首先需要有選擇文件的功能,例如:選擇需要壓縮的文件和選擇需要解壓縮的文件,方法如下:
def choose_compress_file():
'''
選擇需要壓縮的文件
:return:
'''
compress_file_path_name.set(askdirectory())
def choose_uncompress_file():
'''
選擇需要解壓的文件
:return:
'''
uncompress_file_path = askopenfilename()
uncompress_file_path.replace("/", "\\\\") # 字符轉義
uncompress_file_path_name.set(uncompress_file_path)
2、選擇文件的功能有了,就需要思考一個問題:解壓的文件需要有一個解壓的目錄,所以此處還需要一個解壓到某個目錄的方法,如下:
def choose_uncompress_dir():
'''
選擇解壓到的目錄
:return:
'''
uncompress_file_terminal_path_name.set(askdirectory())
3、然後,壓縮、解壓成功或者失敗後是不是得需要設置一些信息進行以下提示,這裏又需要壓縮或解壓成功、失敗的提示信息方法,如下所示:
def compress_file_success_message():
'''
壓縮文件成功後,彈出信息框
:return:
'''
tkinter.messagebox.askokcancel(title='success', message='壓縮成功!')
def uncompress_file_success_message():
'''
解壓文件成功後,彈出信息框
:return:
'''
tkinter.messagebox.askokcancel(title='success', message='解壓成功!')
def uncompress_file_failure_message():
'''
解壓失敗彈出框
:return:
'''
tkinter.messagebox.askokcancel(title='failed', message='這不是zip壓縮文件!')
4、這些基本方法設置完之後,就到了核心模塊了——壓縮和解壓縮的方法。
def compress_file():
'''
壓縮文件
:return:
'''
# 給壓縮文件加上.zip
compress_file_name = compress_file_path_name.get() + '.zip'
# 寫入
zip = zipfile.ZipFile(compress_file_name, 'w', zipfile.ZIP_DEFLATED)
# 遍歷目錄路徑、目錄名、文件名
for dirpath, dirnames, filenames in os.walk(compress_file_path_name.get()):
fpath = dirpath.replace(compress_file_path_name.get(), '')
fpath = fpath and fpath + os.sep or ''
# 迭代文件名
for filename in filenames:
zip.write(os.path.join(dirpath, filename), fpath + filename) # 寫入
zip.close()
# 壓縮成功,彈出信息框
compress_file_success_message()
def upcompress_file():
'''
解壓縮文件
:return:
'''
# 判斷是否爲壓縮文件,以文件後綴是否爲.zip爲判斷依據
is_true = zipfile.is_zipfile(uncompress_file_path_name.get())
if is_true:
# 讀取壓縮文件
unzip = zipfile.ZipFile(uncompress_file_path_name.get(), 'r')
# 遍歷文件
for file in unzip.namelist():
# 輸出文件
unzip.extract(file, uncompress_file_terminal_path_name.get())
# 解壓成功,彈出信息框
uncompress_file_success_message()
else:
# 解壓失敗,彈出信息框
uncompress_file_failure_message()
5、當然還得需要咱們的圖形用戶界面,所以此處還是設置一個圖形用戶界面的方法,如下:
def graphical_user_interface():
'''
圖形用戶界面
:return:
'''
# label:ow代表label是放在第幾行,column是放在第幾列
Label(root, text='壓縮文件路徑:').grid(row=0, column=0)
# entry:獲取輸入
Entry(root, textvariable=compress_file_path_name).grid(row=0, column=1)
# 操作按鈕
Button(root, text='選擇壓縮文件', command=choose_compress_file).grid(row=0, column=2)
# label標籤
Label(root, text='解壓文件路徑:').grid(row=1, column=0)
# 獲取輸入
Entry(root, textvariable=uncompress_file_path_name).grid(row=1, column=1)
# 操作按鈕
Button(root, text='選擇解壓文件', command=choose_uncompress_file).grid(row=1, column=2)
# label標籤
Label(root, text='解壓到:').grid(row=2, column=0)
# 獲取輸入
Entry(root, textvariable=uncompress_file_terminal_path_name).grid(row=2, column=1)
# 操作按鈕
Button(root, text='選擇解壓路徑', command=choose_uncompress_dir).grid(row=2, column=2)
# 操作按鈕
Button(root, text='點擊壓縮', command=compress_file).grid(row=3, column=0)
# 操作按鈕
Button(root, text='點擊解壓', command=upcompress_file).grid(row=3, column=2)
# 操作按鈕
Button(root, text='退出', command=root.quit).grid(row=4, column=1)
# 顯示操作界面
root.mainloop()
至此,所需要的所有方法均已經設置完畢。是時候進行測試了~
三、測試
if __name__ == '__main__':
# 初始化,並設置文件名稱
root = Tk(className='輕壓-極簡版')
# 設置標題,與root = Tk(className='輕壓-極簡版')有異曲同工之妙
# root.title('輕壓')
# 設置壓縮屏幕大小
# root.geometry('1000x150')
# 設置壓縮圖標
# root.iconbitmap(default='xzw.ico')
# 顯示需要壓縮的文件路徑名
compress_file_path_name = StringVar()
# 顯示需要解壓的文件路徑名
uncompress_file_path_name = StringVar()
# 顯示文件想要解壓到的路徑名
uncompress_file_terminal_path_name = StringVar()
# 函數調用,顯示圖形用戶界面
graphical_user_interface()
測試結果如下:
點擊相應的按鈕可以進行壓縮和解壓縮的操作~ 這樣又暴露出了一個問題,如果別人想用這個軟件,但是又不具備Python環境,這樣該怎麼辦呢?於是便有了一下打包成.exe文件的操作。
四、打包成.exe文件
可以使用pyinstaller命令打包對應的.py文件。pyinstaller命令常用的參數如下所示:
-F, --onefile Py代碼只有一個文件
-D, --onedir Py代碼放在一個目錄中(默認是這個)
-K, --tk 包含TCL/TK
-d, --debug 生成debug模式的exe文件
-w, --windowed, --noconsole 窗體exe文件(Windows Only)
-c, --nowindowed, --console 控制檯exe文件(Windows Only)
-X, --upx 使用upx壓縮exe文件
-o DIR, --out=DIR 設置spec文件輸出的目錄,默認在PyInstaller同目錄
--icon=<FILE.ICO> 加入圖標(Windows Only)
-v FILE, --version=FILE 加入版本信息文件
這裏,我們使用如下命令進行打包:
pyinstaller -w -F -i compressed_software/favicon.ico compressed_software/lkys.py
在控制檯出現如下情況說明打包成功:
打包後的.exe文件會出現在項目的dist目錄下,將其拷貝出來後,如下所示:
點擊運行,如下所示,說明成功:
五、一些並不怎麼愉快的事情
打包成.exe文件後,在運行時發生了一些並不怎麼愉快的事情,首先運行的時候會報一個運行腳本發生錯誤的問題,如下所示:
因爲打包時使用了-w的參數,所以運行.exe文件並沒有啓動Windows窗口,故而再次打包。發現報瞭如下兩個錯誤:
1、_tkinter.TclError: bitmap "xzw.ico" not defined
2、PermissionError: [Errno 13] Permission denied: 'picture.ico'
相關錯誤的解決辦法,有興趣的可以點擊錯誤鏈接查看。
六、源碼
源碼已經同步至GitHub,有興趣的同志可以點此進行查看~ 因爲時間關係,此次壓縮軟件圖形用戶界面做的比較簡陋,只能算是極簡版,往後會慢慢的更新優化用戶界面,相關代碼也會在GitHub上實時更新,本篇文章到此結束,謝謝大家。
你們在此過程中遇到了什麼問題,歡迎留言,讓我看看你們都遇到了哪些問題。