如何将写好的python文件导出为exe(新手经历分享)

前言

大家好,我是北京科技大学的某个学生,因为出差的缘故不得不学习python这门语言,说实话一开始头晕脑胀的,连文件都不会创立,在ChatGPT这位老师(真的很好用,你可以给出输入预期和输出预期,直接帮你生成可行的代码)和某位北航大佬的无私解答下,从零开始构建了一个读取Excel表格数据画图的GUI界面,然后将其打包成为一个exe文件,经过实验可以在没有安装python的电脑上正常运行,鉴于我在打包exe时遇见了种种问题,在网络上搜查资料时也没有找到比较简单详细的教程,就把我自己的一个经历写出来供大家参考吧,希望各位大佬轻喷QAQ。

一、打包工具

python打包工具我用的是pyinstaller,至于介绍的话就不讲了,之前在网上浏览的文章有提到高版本python可能不适用的问题,我也没有遇见(用的3.7版本),下面就介绍打包流程

二、打包流程

1.引入代码

代码如下(我自己写的,比较菜,仅用来举例,大佬勿喷):

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

2.安装pyinstaller并运行打包

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!!
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值