Python實(shí)現(xiàn)將文件打包為exe的完整指南
軟件介紹
因?yàn)槲易罱恢痹谟肞ython制作程序,每次都在cmd界面進(jìn)行打包,每次都要輸出py文件路徑,感覺效率比較低,所以就做了這么一個(gè)小工具。

軟件功能
Python文件路徑
這里是輸入你要打包的py文件,路徑是可以有中文的。
ico路徑
這個(gè)是你打包的exe程序的圖標(biāo),默認(rèn)沒有,當(dāng)然你也可以直接輸入其路徑。
輸出程序路徑
這個(gè)就是你打包好的可執(zhí)行程序路徑,默認(rèn)路徑是:C:\Users\Administrator\dist
不過(guò)我這個(gè)增加了可以自定義輸出路徑,也是支持中文路徑的,然后打包完成之后會(huì)彈窗提醒你是否打開文件路徑。

目前不支持輸出程序路徑名字自定義,后面有時(shí)間再加進(jìn)去吧。
是否運(yùn)行程序時(shí)出現(xiàn)cmd界面
這個(gè)一般是建議不用出現(xiàn)

要不然會(huì)額外多一個(gè)cmd界面,看著也不舒服,沒必要。
源碼提供
下面是我提供的源碼,你們可以直接用,然后就是我文末也提供了打包好了的成品,有需要也可以獲取。
import sys
import os
import subprocess
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QLineEdit,
QPushButton, QVBoxLayout, QHBoxLayout, QWidget,
QFileDialog, QTextEdit, QMessageBox, QProgressBar,
QCheckBox) # 新增QCheckBox導(dǎo)入
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QIcon
class PackagerThread(QThread):
"""打包進(jìn)程的線程類,避免UI卡頓"""
log_signal = pyqtSignal(str)
progress_signal = pyqtSignal(int)
finished_signal = pyqtSignal(bool, str)
def __init__(self, python_file, icon_file=None, no_console=False, output_dir=None):
super().__init__()
self.python_file = python_file
self.icon_file = icon_file
self.no_console = no_console # 是否不顯示CMD界面
self.output_dir = output_dir # 自定義輸出目錄
def run(self):
try:
# 檢查文件是否存在
if not os.path.exists(self.python_file):
self.log_signal.emit(f"錯(cuò)誤:文件 {self.python_file} 不存在")
self.finished_signal.emit(False, "文件不存在")
return
# 檢查是否安裝了pyinstaller
try:
subprocess.check_output(["pyinstaller", "--version"],
stderr=subprocess.STDOUT,
text=True)
except (subprocess.CalledProcessError, FileNotFoundError):
self.log_signal.emit("錯(cuò)誤:未安裝pyinstaller,請(qǐng)先安裝:pip install pyinstaller")
self.finished_signal.emit(False, "未安裝pyinstaller")
return
# 構(gòu)建pyinstaller命令
cmd = ["pyinstaller", "--onefile", "--name", os.path.splitext(os.path.basename(self.python_file))[0]]
# 添加無(wú)控制臺(tái)參數(shù)(-w)
if self.no_console:
cmd.append("--windowed") # 等價(jià)于-w,不顯示控制臺(tái)
self.log_signal.emit("已啟用:運(yùn)行時(shí)不顯示CMD界面")
# 添加自定義輸出目錄(--distpath)
if self.output_dir and os.path.isdir(self.output_dir):
cmd.extend(["--distpath", self.output_dir])
self.log_signal.emit(f"自定義輸出目錄:{self.output_dir}")
else:
self.log_signal.emit("使用默認(rèn)輸出目錄(當(dāng)前目錄下的dist文件夾)")
# 如果提供了圖標(biāo)文件,則添加圖標(biāo)參數(shù)
if self.icon_file and os.path.exists(self.icon_file):
cmd.extend(["--icon", self.icon_file])
self.log_signal.emit(f"使用圖標(biāo)文件:{self.icon_file}")
# 添加要打包的Python文件
cmd.append(self.python_file)
self.log_signal.emit(f"開始打包,命令:{' '.join(cmd)}")
self.progress_signal.emit(20)
# 執(zhí)行打包命令
process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1)
# 實(shí)時(shí)輸出日志
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
self.log_signal.emit(output.strip())
self.progress_signal.emit(80)
# 檢查執(zhí)行結(jié)果
exit_code = process.poll()
if exit_code == 0:
# 確定最終輸出目錄(優(yōu)先使用自定義目錄)
dist_dir = self.output_dir if (self.output_dir and os.path.isdir(self.output_dir)) else os.path.join(os.getcwd(), "dist")
exe_path = os.path.join(dist_dir, os.path.splitext(os.path.basename(self.python_file))[0] + ".exe")
self.log_signal.emit(f"打包成功!可執(zhí)行文件位于:{exe_path}")
self.progress_signal.emit(100)
self.finished_signal.emit(True, exe_path)
else:
self.log_signal.emit(f"打包失敗,返回代碼:{exit_code}")
self.finished_signal.emit(False, f"打包失敗,返回代碼:{exit_code}")
except Exception as e:
self.log_signal.emit(f"發(fā)生錯(cuò)誤:{str(e)}")
self.finished_signal.emit(False, str(e))
class PyToExeConverter(QMainWindow):
"""主窗口類"""
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
# 設(shè)置窗口標(biāo)題和大小
self.setWindowTitle("Python轉(zhuǎn)EXE工具@阿幸")
self.setGeometry(100, 100, 800, 650) # 適當(dāng)增加高度容納新控件
# 創(chuàng)建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setSpacing(10)
main_layout.setContentsMargins(20, 20, 20, 20)
# Python文件路徑選擇
python_file_layout = QHBoxLayout()
self.python_file_label = QLabel("Python文件路徑:")
self.python_file_edit = QLineEdit()
self.python_file_btn = QPushButton("瀏覽...")
self.python_file_btn.clicked.connect(self.select_python_file)
python_file_layout.addWidget(self.python_file_label)
python_file_layout.addWidget(self.python_file_edit)
python_file_layout.addWidget(self.python_file_btn)
# 圖標(biāo)文件路徑選擇
icon_file_layout = QHBoxLayout()
self.icon_file_label = QLabel("圖標(biāo)文件路徑(可選):")
self.icon_file_edit = QLineEdit()
self.icon_file_btn = QPushButton("瀏覽...")
self.icon_file_btn.clicked.connect(self.select_icon_file)
icon_file_layout.addWidget(self.icon_file_label)
icon_file_layout.addWidget(self.icon_file_edit)
icon_file_layout.addWidget(self.icon_file_btn)
# 輸出目錄選擇(新增)
output_dir_layout = QHBoxLayout()
self.output_dir_label = QLabel("輸出目錄(可選):")
self.output_dir_edit = QLineEdit()
self.output_dir_btn = QPushButton("瀏覽...")
self.output_dir_btn.clicked.connect(self.select_output_dir)
output_dir_layout.addWidget(self.output_dir_label)
output_dir_layout.addWidget(self.output_dir_edit)
output_dir_layout.addWidget(self.output_dir_btn)
# 無(wú)控制臺(tái)選項(xiàng)(新增)
self.no_console_check = QCheckBox("運(yùn)行EXE時(shí)不顯示CMD界面")
self.no_console_check.setChecked(True) # 默認(rèn)勾選
# 打包按鈕
self.pack_btn = QPushButton("開始打包")
self.pack_btn.clicked.connect(self.start_packaging)
self.pack_btn.setStyleSheet("font-size: 14px; padding: 8px;")
# 進(jìn)度條
self.progress_bar = QProgressBar()
self.progress_bar.setVisible(False)
# 日志輸出區(qū)域
self.log_label = QLabel("打包日志:")
self.log_edit = QTextEdit()
self.log_edit.setReadOnly(True)
self.log_edit.setStyleSheet("background-color: #f0f0f0;")
# 添加所有部件到主布局(新增了輸出目錄和復(fù)選框)
main_layout.addLayout(python_file_layout)
main_layout.addLayout(icon_file_layout)
main_layout.addLayout(output_dir_layout)
main_layout.addWidget(self.no_console_check)
main_layout.addWidget(self.pack_btn, alignment=Qt.AlignCenter)
main_layout.addWidget(self.progress_bar)
main_layout.addWidget(self.log_label)
main_layout.addWidget(self.log_edit)
# 狀態(tài)提示
self.statusBar().showMessage("就緒")
# 新增:選擇輸出目錄
def select_output_dir(self):
dir_path = QFileDialog.getExistingDirectory(
self, "選擇輸出目錄", os.getcwd()
)
if dir_path:
self.output_dir_edit.setText(dir_path)
def select_python_file(self):
"""選擇Python文件"""
file_path, _ = QFileDialog.getOpenFileName(
self, "選擇Python文件", "", "Python Files (*.py);;All Files (*)"
)
if file_path:
self.python_file_edit.setText(file_path)
def select_icon_file(self):
"""選擇圖標(biāo)文件"""
file_path, _ = QFileDialog.getOpenFileName(
self, "選擇圖標(biāo)文件", "", "Icon Files (*.ico);;All Files (*)"
)
if file_path:
self.icon_file_edit.setText(file_path)
def append_log(self, text):
"""添加日志到日志區(qū)域"""
self.log_edit.append(text)
# 自動(dòng)滾動(dòng)到底部
self.log_edit.verticalScrollBar().setValue(
self.log_edit.verticalScrollBar().maximum()
)
def update_progress(self, value):
"""更新進(jìn)度條"""
self.progress_bar.setValue(value)
def start_packaging(self):
"""開始打包過(guò)程"""
python_file = self.python_file_edit.text().strip()
icon_file = self.icon_file_edit.text().strip() if self.icon_file_edit.text().strip() else None
no_console = self.no_console_check.isChecked() # 獲取復(fù)選框狀態(tài)
output_dir = self.output_dir_edit.text().strip() if self.output_dir_edit.text().strip() else None # 獲取輸出目錄
# 驗(yàn)證輸入
if not python_file:
QMessageBox.warning(self, "輸入錯(cuò)誤", "請(qǐng)選擇要打包的Python文件")
return
if not python_file.endswith(".py"):
QMessageBox.warning(self, "文件錯(cuò)誤", "請(qǐng)選擇擴(kuò)展名為.py的Python文件")
return
# 檢查圖標(biāo)文件是否存在(如果提供了的話)
if icon_file and not os.path.exists(icon_file):
QMessageBox.warning(self, "文件錯(cuò)誤", f"圖標(biāo)文件不存在:{icon_file}")
return
# 檢查輸出目錄是否存在(如果提供了的話)
if output_dir and not os.path.isdir(output_dir):
QMessageBox.warning(self, "目錄錯(cuò)誤", f"輸出目錄不存在:{output_dir}")
return
# 準(zhǔn)備打包
self.log_edit.clear()
self.pack_btn.setEnabled(False)
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
self.statusBar().showMessage("正在打包...")
# 創(chuàng)建并啟動(dòng)打包線程(傳入新參數(shù))
self.packager_thread = PackagerThread(
python_file,
icon_file,
no_console=no_console,
output_dir=output_dir
)
self.packager_thread.log_signal.connect(self.append_log)
self.packager_thread.progress_signal.connect(self.update_progress)
self.packager_thread.finished_signal.connect(self.on_packaging_finished)
self.packager_thread.start()
def on_packaging_finished(self, success, message):
"""打包完成后的處理"""
self.pack_btn.setEnabled(True)
self.statusBar().showMessage("打包完成" if success else "打包失敗")
if success:
QMessageBox.information(self, "成功", f"打包成功!\n可執(zhí)行文件位于:\n{message}")
# 詢問(wèn)是否打開輸出目錄
if QMessageBox.question(self, "打開目錄", "是否打開輸出目錄?",
QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
output_dir = os.path.dirname(message)
if os.name == 'nt': # Windows系統(tǒng)
os.startfile(output_dir)
elif os.name == 'posix': # Linux或macOS
subprocess.run(['open' if sys.platform == 'darwin' else 'xdg-open', output_dir])
else:
QMessageBox.critical(self, "失敗", f"打包失敗:\n{message}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = PyToExeConverter()
window.show()
sys.exit(app.exec_())
到此這篇關(guān)于Python實(shí)現(xiàn)將文件打包為exe的完整指南的文章就介紹到這了,更多相關(guān)Python文件打包為exe內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python語(yǔ)言實(shí)現(xiàn)科學(xué)計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Python語(yǔ)言實(shí)現(xiàn)科學(xué)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
python實(shí)現(xiàn)壁紙批量下載代碼實(shí)例
本篇文章通過(guò)代碼實(shí)例給大家分享了用python實(shí)現(xiàn)壁紙批量下載這個(gè)功能,有興趣的朋友參考下吧。2018-01-01
Python的string模塊中的Template類字符串模板用法
通過(guò)string.Template我們可以為Python定制字符串的替換標(biāo)準(zhǔn),這里我們就來(lái)通過(guò)示例解析Python的string模塊中的Template類字符串模板用法:2016-06-06
Windows下PyCharm配置Anaconda環(huán)境(超詳細(xì)教程)
這篇文章主要介紹了Windows下PyCharm配置Anaconda環(huán)境,本文給大家分享一篇超詳細(xì)教程,通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Python可視化mhd格式和raw格式的醫(yī)學(xué)圖像并保存的方法
今天小編就為大家分享一篇Python可視化mhd格式和raw格式的醫(yī)學(xué)圖像并保存的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
Pytorch Conda環(huán)境下載慢換源/刪源/恢復(fù)默認(rèn)源的簡(jiǎn)單操作
隨著實(shí)驗(yàn)增多,需要分割創(chuàng)建環(huán)境的情況時(shí)有出現(xiàn),在此情況下使用conda create --name xx python=3.10 pytorch torchvision pytorch-cuda -c nvidia -c pytorch -y這樣的指令創(chuàng)建時(shí)如果不換源,往往下載速度很慢,本文介紹了解決辦法,需要的朋友可以參考下2024-07-07
Python裝飾器與線程結(jié)合提高接口訪問(wèn)效率方法
這篇文章主要為大家介紹了如何實(shí)現(xiàn)Python裝飾器與線程結(jié)合來(lái)提高接口的訪問(wèn)效率,有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09
實(shí)例詳解Matlab 與 Python 的區(qū)別
Python是一種面向?qū)ο蟮慕忉屝陀?jì)算機(jī)程序設(shè)計(jì)語(yǔ)言。這篇文章主要介紹了Matlab 與 Python 的區(qū)別及優(yōu)勢(shì),感興趣的朋友跟隨小編一起看看吧2019-04-04
Python+tkinter使用40行代碼實(shí)現(xiàn)計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了Python+tkinter使用40行代碼實(shí)現(xiàn)計(jì)算器功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
使用Python實(shí)現(xiàn)畫一個(gè)中國(guó)地圖
今天小編就為大家分享一篇使用Python實(shí)現(xiàn)畫一個(gè)中國(guó)地圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11

