赞
踩
大家好,我是北京科技大学的某个学生,因为出差的缘故不得不学习python这门语言,说实话一开始头晕脑胀的,连文件都不会创立,在ChatGPT这位老师(真的很好用,你可以给出输入预期和输出预期,直接帮你生成可行的代码)和某位北航大佬的无私解答下,从零开始构建了一个读取Excel表格数据画图的GUI界面,然后将其打包成为一个exe文件,经过实验可以在没有安装python的电脑上正常运行,鉴于我在打包exe时遇见了种种问题,在网络上搜查资料时也没有找到比较简单详细的教程,就把我自己的一个经历写出来供大家参考吧,希望各位大佬轻喷QAQ。
python打包工具我用的是pyinstaller,至于介绍的话就不讲了,之前在网上浏览的文章有提到高版本python可能不适用的问题,我也没有遇见(用的3.7版本),下面就介绍打包流程
代码如下(我自己写的,比较菜,仅用来举例,大佬勿喷):
import pandas as pd import matplotlib.pyplot as plt import tkinter as tk from tkcalendar import DateEntry from tkinter import filedialog from datetime import date #几个按钮的触发事件设计 #region my code block # Excel文件打开函数 def import_button_click(): global df file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx;*.xls")]) if file_path: # 使用pandas读取Excel文件 df = pd.read_excel(file_path, engine='openpyxl') # print(df) # 两天绘图按钮2点击 def print_button2_click(): global df df2 = df # 得到日历信息 calenda_data3 = root.date_entry3.get_date() calenda_data4 = root.date_entry4.get_date() calenda_data3 = pd.to_datetime(calenda_data3) calenda_data4 = pd.to_datetime(calenda_data4) if calenda_data3 <= calenda_data4: NUM = 0 if NUM == 0: dates = pd.to_datetime(df['日期']) # print(dates) # 绘制每个元素的折线图 i = -1 for date in dates: i = i + 1 if (date != calenda_data3 and date != calenda_data4): df2 = df2.drop(i) # dates = dates[(dates == calenda_data3) | (dates == calenda_data4)] df2['日期'] = pd.to_datetime(df2['日期']) # 设置日期列为索引 df2.set_index('日期', inplace=True) # 使用 plot 绘制折线图,交换 x 和 y 的位置 ax=df2.T.plot(marker='o', linestyle='-') # 添加标题和标签 ax.set_xticks(range(0, len(df2.columns))) ax.set_xticklabels(df2.columns) # 设置 x 轴标签为元素的列名 plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title('日期下不同元素的值的变化',fontproperties='SimHei') plt.xlabel('元素',fontproperties='SimHei') plt.ylabel('日期',fontproperties='SimHei') # 显示图形 plt.show() NUM = NUM + 1 else:print("日期输入错误") # 一段时间绘图1按钮点击 def print_button_click(): global df df2 = df # 得到下拉栏信息 option_info = selected_option.get() # 得到日历信息 calenda_data1 = root.date_entry1.get_date() calenda_data2 = root.date_entry2.get_date() calenda_data1 = pd.to_datetime(calenda_data1) calenda_data2 = pd.to_datetime(calenda_data2) if calenda_data1 <= calenda_data2: if option_info == "全元素": NUM = 0 if NUM == 0: dates = pd.to_datetime(df['日期']) # print(dates) # 绘制每个元素的折线图 i = -1 for date in dates: i = i + 1 if (date < calenda_data1 or date > calenda_data2): df2 = df2.drop(i) # print(df2) # for element in df2.columns[1:]: dates = dates[dates >= calenda_data1] dates = dates[dates <= calenda_data2] for element in df2.columns[1:]: plt.plot(dates, df2[element], label=element) # 添加标题、标签和图例,精简x轴数据显示 unique_x_values = list(set(dates)) plt.xticks(unique_x_values) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title(option_info + '折线图', fontproperties='SimHei') plt.xlabel('日期', fontproperties='SimHei') plt.ylabel('元素值', fontproperties='SimHei') plt.legend(loc='upper right') # 格式化日期显示 plt.gca().xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m-%d')) # 自动调整日期标签的显示以防止重叠 plt.gcf().autofmt_xdate() # 显示图形 plt.show() NUM = NUM + 1 if option_info != "全元素": NUM = 0 if NUM == 0: dates = pd.to_datetime(df['日期']) # print(dates) # 绘制每个元素的折线图 i = -1 for date in dates: i = i + 1 if (date < calenda_data1 or date > calenda_data2): df2 = df2.drop(i) # print(df2) # for element in df2.columns[1:]: dates = dates[dates >= calenda_data1] dates = dates[dates <= calenda_data2] for element in df2.columns[1:]: if(element==option_info): plt.plot(dates, df2[element], label=element) # 添加标题、标签和图例,精简x轴数据显示 unique_x_values = list(set(dates)) plt.xticks(unique_x_values) plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 plt.title(option_info + '折线图', fontproperties='SimHei') plt.xlabel('日期', fontproperties='SimHei') plt.ylabel('元素值', fontproperties='SimHei') plt.legend(loc='upper right') # 格式化日期显示 plt.gca().xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m-%d')) # 自动调整日期标签的显示以防止重叠 plt.gcf().autofmt_xdate() # 显示图形 plt.show() NUM = NUM + 1 else:print("日期输入错误") #endregion # 页面设计 #region My Code Block df = "文件内的信息" sof = "下拉栏中的信息" root = tk.Tk() root.title("导入Excel文件") # 添加标签 label = tk.Label(root, text="请点击按钮选择Excel文件") label.pack(pady=20) # 添加导入按钮 import_button = tk.Button(root, text="导入Excel文件", command=import_button_click) import_button.pack() # 添加绘图按钮 # 显示一段时间 print_button = tk.Button(root, text="一段时间绘图", command=print_button_click) print_button.pack(side=tk.LEFT, padx=5) # 显示两天的对比 print_button2 = tk.Button(root, text="两天比较绘图", command=print_button2_click) print_button2.pack(side=tk.LEFT, padx=5) # 添加下拉框 # 创建下拉框选项 options = ["全元素", "元素1", "元素2", "元素3", "元素4", "元素5", "元素6", "元素7", "元素8", "元素9", "元素10"] # 创建变量以存储选中的选项 selected_option = tk.StringVar(root) selected_option.set(options[0]) # 设置默认选项 # 创建下拉框 option_menu = tk.OptionMenu(root, selected_option, *options) option_menu.pack(pady=20) # selected_option.trace_add("write", option_selected) # 添加标签 label2 = tk.Label(root, text="左边为一段时间,右边为只看这两天") label2.pack(pady=20) # 创造日历选择 # 添加四个日期选择器到你的现有界面 root.date_entry1 = DateEntry(root, width=12, background='darkblue', foreground='white', borderwidth=2) root.date_entry1.pack(side=tk.LEFT, padx=10, pady=10) root.date_entry2 = DateEntry(root, width=12, background='darkblue', foreground='white', borderwidth=2) root.date_entry2.pack(side=tk.LEFT, padx=10, pady=10) root.date_entry3 = DateEntry(root, width=12, background='darkblue', foreground='white', borderwidth=2) root.date_entry3.pack(side=tk.LEFT, padx=10, pady=10) root.date_entry4 = DateEntry(root, width=12, background='darkblue', foreground='white', borderwidth=2) root.date_entry4.pack(side=tk.LEFT, padx=10, pady=10) # 启动主循环 root.mainloop() #endregion
1.在pycharm的终端这里点击一下
2.在打开的终端页面输入以下代码下载pyinstaller
如果下载不了的话可以看看网上解决方法,我的是蛮顺利的。
代码如下(示例):
pip install pyinstaller
3.输入你文件的路径,
路径可以在这里看到,直接复制就行。
还是在终端输入cd+空格+粘贴你刚才复制的路径
4.打包你用到的库和模板
库和模板可以在开头看见,虽然有些库和模板没有写在开头,但是我们后面可以补上去(就跟有人没票坐火车一样,先挤上去,等后面再补票),先把这些写在开头的打包掉(这是有票的乘客),代码形式:pyinstaller --hidden-import 库A–hidden-import --hidden-import 库B python文件名+.py,同样写在终端里。
我的代码如下:
pyinstaller --hidden-import pandas --hidden-import matplotlib --hidden-import tkinter --hidden-import tkcalendar --hidden-import openpyxl --hidden-import babel main.py
这里我的两个库并没有在开头出现,但是我在代码中使用了,这里忘记了自己导入的库也不要害怕,先把开头的导进去,后面有补票的办法。
这一步成功的话会生成一个dist文件夹,里面是我们的exe文件,还有一个SPEC文件,它的用处就是我们用来补票的,这个我们后面的步骤再聊。
5.打包代码
pyinstaller -F -w+空格+python文件名+.py,在这个命令中,pyinstaller 是打包工具的名称,-F 表示生成单个可执行文件(打包为单个文件),-w 表示在运行时不显示控制台窗口(仅限 Windows 系统),而文件名则是你的 Python 脚本文件的名称,同样我们把指令写到终端里,代码如下
pyinstaller -F -w main.py
在dist文件夹下(文件夹在你的python文件位置,忘了的话回步骤3看)我们就能找到生成的exe文件(应用程序),我们打开它
如果可以正常运行,那么恭喜你已经完成所有步骤,如果想在其他电脑上使用,只需要把exe文件(应用程序)这个东西复制粘贴到其他电脑中就行,如果出现如图所示的报错
是因为之前导入的库或模块不全导致了不能识别代码中的一部分(相当于没买票上车的人被乘务员发现了),那么请看接下来的报错处理部分(乖乖补票)。
6.报错处理
我们发现报错是因为缺少一个名字为’babel.numbers’的模块(这个坏同志没买票),我们现在来手动把它添加,回到之前的文件夹。
我们用笔记本打开SPEC文件,这个文件就是乘务员让我们补票的地方。
找到标蓝的地方,把刚才警告中显示缺少的库或者模板添加进去,添加的格式如下:
hiddenimports=['babel.numbers'],
多项的话就这么写:
hiddenimports=['U','S','T','B'],
保存后关闭文本。
回到pycharm的终端,输入pyinstaller python文件名.spec
等待成功改写后,我们再次打开exe文件(应用程序),发现已经可以运行了(还不行的话看看还有没有落下的库,重复步骤6,不然我也无能为力了)
这时候我们就可以把exe文件复制出来发给别的电脑用了。
7.删除文件
如果删除dist文件夹和SPEC文件的话,对原来代码的运行是没有影响的,这只是我们打包时产生的输出,如果看着碍眼,打包成功后可以直接扔到垃圾桶里,在我们整个打包过程中也可以随时删除,反正每次打包的时候如果有这个文件夹就把旧的改了写在里面,没有的话系统会自动创建一个写在里面。
希望新的一年里北交和北科合并成,成为985大学,直接进行一个学历升值。
祝大家新年快乐,写的代码永远一次通过,永远没有BUG!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。