技術場景:
需分發的Python工具要求終端用戶可動態修改執行邏輯將Python環境與指定庫(如NumPy/Pandas)嵌入可執行文件實現"一次打包,動態擴展"的輕量化解決方案。
▌ 架構設計原理
1. 雙模運行時識別
# 核心判斷邏輯(適配開發模式與編譯模式)
def get_runtime_path(): if getattr(sys, 'frozen', False): return os.path.dirname(sys.executable) # 編譯模式取執行文件路徑 return os.path.dirname(__file__) # 開發模式取腳本路徑
設計優勢:
- 開發階段與發布版本使用同一套代碼
- 避免硬編碼路徑引發的跨平臺兼容問題
2. 動態腳本加載機制
def load_script(script_name): target_path = os.path.join(get_runtime_path(), script_name) if os.path.exists(target_path): with open(target_path, 'r', encoding='utf-8') as f: exec(f.read(), globals()) # 在全局命名空間執行腳本
3. 架構圖
▌ 基礎功能實現
1. 編寫main.py和Run.py文件(名稱隨意)
main.py
import os
import sys# === 預先導入之后可能會用到的模塊 ===
import numpy
import pandas# 核心判斷邏輯(適配開發模式與編譯模式)
def get_runtime_path(): if getattr(sys, 'frozen', False): return os.path.dirname(sys.executable) # 編譯模式取執行文件路徑 return os.path.dirname(__file__) # 開發模式取腳本路徑# 這里一定要定義一個main函數
def main():# 導入一個可以被修改的腳本代碼“Run.py”,后續可以通過它指定要被運行的腳本current_path = get_runtime_path()ScriptPath = os.path.join(current_path, "Run.py")if os.path.isfile(ScriptPath):with open(ScriptPath, 'r', encoding='utf-8') as file:exec(file.read(),globals())# 程序入口
if __name__ == "__main__":main()
Run.py
import os
import sys# 核心判斷邏輯(適配開發模式與編譯模式)
def get_runtime_path(): if getattr(sys, 'frozen', False): return os.path.dirname(sys.executable) # 編譯模式取執行文件路徑 return os.path.dirname(__file__) # 開發模式取腳本路徑def load_script(script_name): target_path = os.path.join(get_runtime_path(), script_name) if os.path.exists(target_path): with open(target_path, 'r', encoding='utf-8') as f: exec(f.read(), globals()) # 在全局命名空間執行腳本 # def main():script_name = "example_1.py"
load_script(script_name)script_name = "example_2.py"
load_script(script_name)# if __name__ == "__main__":
# main()
由于實際運行時上方代碼Run.py由main.exe調用,將直接和main.exe共用全局命名空間中的os和sys庫,因此
2. 編譯 main.py :
pyinstaller --onedir main.py
若沒有安裝pyinstaller,請先使用pip安裝:
pip install pyinstaller
編譯完的文件如下:
your_project_folder/
│
├──── build/ → 沒有用,可以刪除
├──── dist/ → 打包后的程序文件夾
│ └─── main/
│ ├─── _internal/ → 需要用到的庫文件會被放在這里
│ └─── main.exe → 打包后的可執行程序
│
└──── main.spec → 打包配置文件,可以修改它來定制打包過程
_internal/ 和 main.exe → 可以一起拿出來放在其它位置(需放在同一路徑下)
3. 測試運行效果
運行 main.exe :
test_main.bat
.\main.exe
pause
運行 test_main.bat 文件,查看效果:
D:\test>.\main.exe
This script is running as a compiled executable.
This script is running as a compiled executable.
一維數組:
[1 2 3 4 5]
一維數組加10:
[11 12 13 14 15]
一維數組乘2:
[ 2 4 6 8 10]
二維數組:
[[1 2][3 4]]
矩陣乘法結果:
[[ 7 10][15 22]]
原始DataFrame:Name Age City
0 Alice 24 New York
1 Bob 27 Los Angeles
2 Charlie 22 Chicago
3 David 32 Houston年齡大于25的行:Name Age City
1 Bob 27 Los Angeles
3 David 32 Houston按年齡升序排序后的DataFrame:Name Age City
2 Charlie 22 Chicago
0 Alice 24 New York
1 Bob 27 Los Angeles
3 David 32 Houston描述性統計量:Age
count 4.000000
mean 26.250000
std 4.349329
min 22.000000
25% 23.500000
50% 25.500000
75% 28.250000
max 32.000000D:\test>pause
請按任意鍵繼續. . .
▌ 例程(附)
example_1.py
import numpy as np# 創建一個一維數組
arr1 = np.array([1, 2, 3, 4, 5])# 創建一個二維數組(矩陣)
arr2 = np.array([[1, 2], [3, 4]])# 數組加法
arr_sum = arr1 + 10# 數組乘法(元素級)
arr_prod = arr1 * 2# 矩陣乘法
mat_prod = np.dot(arr2, arr2)# 打印結果
print("一維數組:")
print(arr1)
print("一維數組加10:")
print(arr_sum)
print("一維數組乘2:")
print(arr_prod)
print("二維數組:")
print(arr2)
print("矩陣乘法結果:")
print(mat_prod)
運行結果:(example_1.py)
一維數組:
[1 2 3 4 5]
一維數組加10:
[11 12 13 14 15]
一維數組乘2:
[ 2 4 6 8 10]
二維數組:
[[1 2][3 4]]
矩陣乘法結果:
[[ 7 10][15 22]]
example_2.py
import pandas as pd# 創建一個簡單的DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David'],'Age': [24, 27, 22, 32],'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)# 顯示DataFrame
print("原始DataFrame:")
print(df)# 數據篩選:選擇年齡大于25的行
filtered_df = df[df['Age'] > 25]
print("\n年齡大于25的行:")
print(filtered_df)# 數據排序:按年齡升序排序
sorted_df = df.sort_values(by='Age')
print("\n按年齡升序排序后的DataFrame:")
print(sorted_df)# 計算描述性統計量
stats = df.describe()
print("\n描述性統計量:")
print(stats)
運行結果:(example_2.py)
原始DataFrame:Name Age City
0 Alice 24 New York
1 Bob 27 Los Angeles
2 Charlie 22 Chicago
3 David 32 Houston年齡大于25的行:Name Age City
1 Bob 27 Los Angeles
3 David 32 Houston按年齡升序排序后的DataFrame:Name Age City
2 Charlie 22 Chicago
0 Alice 24 New York
1 Bob 27 Los Angeles
3 David 32 Houston描述性統計量:Age
count 4.000000
mean 26.250000
std 4.349329
min 22.000000
25% 23.500000
50% 25.500000
75% 28.250000
max 32.000000