Pyinstaller - “致命错误!将脚本转换为 exe 时无法执行脚本”

Posted

技术标签:

【中文标题】Pyinstaller - “致命错误!将脚本转换为 exe 时无法执行脚本”【英文标题】:Pyinstaller - “Fatal error ! Failed to execute script” when converting script to exe 【发布时间】:2021-07-17 06:50:20 【问题描述】:

我有一个用 tkinter 构建的 GUI,它通过从 excel 文件中读取链接来进行网络抓取,然后将所有结果存储在 excel 文件中。此外,它还有一些按钮,允许从 excel 文件中绘制数据,做一些简单的过滤器。我在 Pycharm 中正确构建了它。现在,我需要构建一个 exe 文件,为此我使用 pyinstaller 和此代码 pyinstaller.exe --onefile --windowed main.py。问题是它给出了一个致命错误并且无法执行脚本。我已经尝试在我的环境中安装 cmd 中的所有软件包,但错误仍然存​​在。 这里我放了我的 main.py(这里是 link 到 github,functions.py 和输入数据在哪里):

from tkinter import messagebox
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfile
from functions import *
import os
import threading

excel_QS_resultados = os.path.dirname(__file__) + "/Resultados_QS"
excel_ponderacion_name = os.path.dirname(__file__) + "/Ponderación_Metologías"
def open_file():
    browse_text.set("Ejecutando...")
    file = askopenfile(parent = root, mode = "rb", title = "Elija un archivo", filetype = [("Excel file", "*.xlsx")])

    if file:
        if not os.path.exists(os.path.dirname(__file__) + "/Tablas"):
            os.mkdir(os.path.dirname(__file__) + "/Tablas")
        #print(os.getcwd())
        guardar_tablas(file.name[:-5], os.path.dirname(__file__) + "/Tablas",
                       excel_QS_resultados, root)
 
        browse_text.set("Cargar tablas de las webs de rankings")

def to_plot(kind, latam = False):
    file = askopenfile(parent=root, mode="rb", title="Elija un archivo", filetype=[("Excel file", "*.xlsx")])
    if file:
        if "QS" in os.path.basename(os.path.normpath(file.name[:-5])):
            ranking_name = "QS"
            subjects_QS = 0: os.path.basename(os.path.normpath(file.name[:-5]))[3:]
            subjects_THE = 
        else:
            ranking_name = "THE"
            subjects_THE = 0: os.path.basename(os.path.normpath(file.name[:-5]))[4:]
            subjects_QS = 

        df_subject = pd.read_excel(file.name)
        if ranking_name == "QS":
            list_years, list_years_2 = Get_If_UniRanked(df_subject, ranking_name, excel_QS_resultados, subjects_QS,
                                                        0)  # También imprime años rankeados

            list_years_rank = ["La PUCP fue rankeada en el año " + str(year) for year in list_years]
            list_years_result = ["Se tienen los resultados de la PUCP en el año " + str(year) for year in list_years_2]

            if list_years_rank == []:
                list_years_rank.append("La PUCP no fue rankeada en ninguno de los años")

            if list_years_result == []:
                list_years_result.append("No se tienen resultados de la PUCP en ninguno de los años")

            top = Toplevel(root)
            canvas2 = Canvas(top, width=600, height=300)
            canvas2.pack()

            header = Frame(canvas2, width=500, height=200, bg =  "#14a4d6")
            header.grid(columnspan=5, rowspan=2, row=0)

            header1 = Frame(canvas2, width=500, height=15, bg =  "#14a4d6")
            header1.grid(columnspan=3, rowspan=1, row=1)

            main_content = Frame(canvas2, width=500, height=100, bg="#14a4d6")
            main_content.grid(columnspan=5, row=2)

            display_text_box("\n".join(map(str, list_years_rank + list_years_result)), 0, 1, canvas2)

            instructions = Label(header1, text="Seleccione el año ",font="Raleway")
            instructions.grid(column=1, row=2)

            for i in range(len(list_years)):
                button = Button(main_content, text=list_years[i], font=("shanti", 10), height = 1, width = 6)
                button.grid(column=i, row=1, padx = 15, pady = 15)

        else:
            list_years = Get_If_UniRanked(df_subject, ranking_name, excel_QS_resultados, subjects_THE, 0)

            list_years_rank = ["La PUCP fue rankeada en el año " + str(year) for year in list_years]

            if list_years_rank == []:
                list_years_rank.append("La PUCP no fue rankeada en ninguno de los años")

            top = Toplevel(root)
            canvas2 = Canvas(top, width=600, height=300)
            canvas2.pack()

            header = Frame(canvas2, width=500, height=200, bg="#14a4d6")
            header.grid(columnspan=5, rowspan=2, row=0)

            header1 = Frame(canvas2, width=500, height=15, bg="#14a4d6")
            header1.grid(columnspan=3, rowspan=1, row=1)

            main_content = Frame(canvas2, width=500, height=100, bg="#14a4d6")
            main_content.grid(columnspan=5, row=2)

            display_text_box("\n".join(map(str, list_years_rank )), 0, 1, canvas2)

            instructions = Label(header1, text="Seleccione el año ", font="Raleway")
            instructions.grid(column=1, row=2)

    if kind  ==3:
        list_years = list_years_2[::-1]
    for i in range(len(list_years)):
        button = Button(main_content, text=list_years[i], font=("shanti", 10), height=1, width=6,
                        command =lambda i=i: plot(file, ranking_name, subjects_THE, subjects_QS, str(list_years[i]), kind, latam))
        button.grid(column=i, row=1, padx=15, pady=15)

def plot(file, ranking_name, subjects_THE, subjects_QS, year, kind, latam):
    df_subject = pd.read_excel(file.name)
    df_with_method = apply_methodology_continent(df_subject, excel_ponderacion_name, ranking_name, 0,
                                                 subjects_THE, subjects_QS).copy()
    time = datetime.datetime.now().time().strftime("%H-%M-%S")
    if ranking_name == "QS":
        df_with_method.to_excel(os.path.dirname(__file__) + "/" + ranking_name + " " + subjects_QS[0] + " " + time + ".xlsx",
                                index=False)
    elif ranking_name == "THE":
        df_with_method.to_excel(os.path.dirname(__file__) + "/" +  ranking_name + " " + subjects_THE[0] + " " + time + ".xlsx",
                                index=False)
    else:
        pass  # datetime.datetime.now().time().strftime("%H:%M:%S")

    if kind == 1:
        df_6Higher_Uni = Get_6Higher_Uni(df_with_method, int(year), ranking_name, latam)
        if df_6Higher_Uni is not None:
            Plot_6Higher_Uni(df_6Higher_Uni, ranking_name, latam)
            Plot_6HigherUni_Contribution(df_6Higher_Uni, excel_ponderacion_name, subjects_QS,
                                         subjects_THE, 0, ranking_name, latam)
        else:
            messagebox.showwarning("Advertencia",
                                   "Existen datos incompletos en el mismo rango de puestos que la PUCP. Analice un año anterior.")
    elif kind == 2:
        df_6Bottom_Uni = Get_6Bottom_Uni(df_with_method, int(year), ranking_name, latam)
        if df_6Bottom_Uni is not None:
            Plot_6Higher_Uni(df_6Bottom_Uni, ranking_name, latam)
            Plot_6HigherUni_Contribution(df_6Bottom_Uni, excel_ponderacion_name, subjects_QS,
                                         subjects_THE, 0, ranking_name, latam)
        else:
            messagebox.showwarning("Advertencia",
                                   "Existen datos incompletos en el mismo rango de puestos que la PUCP. Analice un año anterior.")
    else:
        df_6Bottom_Uni = Get_6Bottom_Uni_QS_Result(df_with_method, int(year), excel_ponderacion_name,
                                                   excel_QS_resultados, 0, subjects_QS, latam)
        if df_6Bottom_Uni is not None:
            Plot_6Higher_Uni(df_6Bottom_Uni, ranking_name, latam)
            Plot_6HigherUni_Contribution(df_6Bottom_Uni, excel_ponderacion_name, subjects_QS,
                                         subjects_THE, 0, ranking_name, latam)
        else:
            messagebox.showwarning("Advertencia",
                                   "Existen datos incompletos en el mismo rango de puestos que la PUCP. Analice un año anterior.")

root = Tk()
root.iconbitmap("C:/Users/Franco/PycharmProjects/THE_QS/icon.ico")
root.title("Generador de gráficos- Rankings THE y QS by Subject")

header = Frame(root, width=800, height=150)
header.grid(columnspan=3, rowspan=2, row=0)

main_content = Frame(root, width=800, height=150, bg="#14a4d6")
main_content.grid(columnspan=3, rowspan=4, row=4)

btn_options = ["R - Siguientes 6 Univ. Rankeadas Global",
                    "R - Siguientes 6 Univ. Rankeadas LATAM",
                    "NR/R - Últimas 6 Universidades Rankeadas Global",
                    "NR/R - Últimas 6 Universidades Rankeadas LATAM",
                    "NR - QS Últimas Universidades Rankeadas Global",
                    "NR - QS Últimas Universidades Rankeadas LATAM"]


next6Global_btn = Button(root, text = btn_options[0], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 1))
next6Latam_btn = Button(root, text = btn_options[1], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 1, latam=True))
last6Global_btn = Button(root, text = btn_options[2], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 2))
last6Latam_btn = Button(root, text = btn_options[3], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 2, latam=True))
QSlast6Global_btn = Button(root, text = btn_options[4], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 3))
QSlast6Latam_btn = Button(root, text = btn_options[5], font=("shanti", 10), height = 1, width = 40, command = lambda: to_plot(kind = 3, latam=True))

next6Global_btn.grid(row = 4, column = 1)
next6Latam_btn.grid(row = 4, column = 2)
last6Global_btn.grid(row = 5, column = 1)
last6Latam_btn.grid(row = 5, column = 2)
QSlast6Global_btn.grid(row = 6, column = 1)
QSlast6Latam_btn.grid(row = 6, column = 2)

# logo
display_logo("C:/Users/Franco/PycharmProjects/THE_QS/pucp-logo.png", 0, 1)

# instructions
instructions = Label(root, text="Seleccione el archivo excel con los enlaces de los rankings by subject", font="Raleway")
instructions.grid(columnspan=4, rowspan= 3, column=1, row=1)


# browse
browse_text = StringVar()
browse_text.set("Cargar tablas de las webs de rankings")
browse_btn = Button(root, textvariable = browse_text, font="Raleway", bg="#14a4d6",
                       command = lambda: threading.Thread(target=open_file).start(), fg="white", height=2, width=35)

browse_btn.grid(columnspan = 3, column=1, row=2)


root.mainloop()

我非常感谢您对此提供的帮助,因为我已经尝试了一段时间但没有成功。


更新

在几个月没有完成这个项目之后,我想证明我从你那里得到的一些新建议。 我尝试了@Blueman7 关于缺少icon=part 的建议,我在 cmd 中使用的命令如下(以防我在执行时出错,因为它仍然不起作用但有一些改进):

cd 项目路径 conda 激活环境名称 pyinstaller.exe --onefile --icon=icon.ico main.py

执行此命令后,我得到了一个带有 icon.ico 的 main.exe。当我尝试运行此 .exe 时,它​​会打开一个黑色窗口并保持大约 1 分钟,此时它在与 pyzmq 包相关的图像中出现错误。

我尝试将此文件夹 pyzmq.libs 复制到我当前的项目路径并在 cmd 中运行命令pyinstaller.exe --onefile --icon=icon.ico --add-data "./pyzmq.libs;." main.py。另外,我尝试将 pyzmq 导入我的 conda 环境,但到目前为止它都不起作用。 非常感谢您的建议。

【问题讨论】:

【参考方案1】:

在您的代码中,您忘记提及 icon=part。

pyinstaller.exe --onefile --windowed --icon=yourico.ico main.py

【讨论】:

谢谢,它帮助了我,但现在它给我带来了一个新错误(我已经在我的帖子中更新了这个。)【参考方案2】:

对我有用的只是:

pyinstaller --onefile main.py

没有 -windowed 或 -w

【讨论】:

【参考方案3】:

提供您获得的错误的屏幕截图始终有助于理解您的问题。

但是根据您提供的信息,我认为您的问题出在您正在使用的命令上,应该是,

pyinstaller --onefile --windowed main.py

有关如何使用 pyinstaller 创建可执行文件的详细信息,请查看 -> https://datatofish.com/executable-pyinstaller/

如果这不起作用,请尝试使用py2exe

看看这个,

https://stackabuse.com/creating-executable-files-from-python-scripts-with-py2exe

【讨论】:

你能提供你得到的错误吗! 如果 pyinstaller 不起作用,请尝试使用 py2exe 或其他此类软件包。【参考方案4】:

试试:

pyinstaller onefile -w main.py

这行得通吗?

【讨论】:

以上是关于Pyinstaller - “致命错误!将脚本转换为 exe 时无法执行脚本”的主要内容,如果未能解决你的问题,请参考以下文章

pyinstaller打包

pyinstaller打包动态库

PyInstaller 怎么在linux安装和使用

python 使用pyinstaller打包程序

用pyinstaller打包出现找不到指定的模块?

Python打包方法——Pyinstaller (python3)