Pyinstaller EXE 只会从 CMD 运行,点击 EXE 不起作用

Pyinstaller EXE will only run from CMD, clicking on the EXE doesn't work

我为我的一个朋友制作了一个简单的 python 程序,它使用了 tkinterSMTPlib。 我使用 pyinstaller 为程序制作了一个 .exe,但是当我双击 .exe 时,我的 CMD 终端会在屏幕上闪烁一秒钟然后消失。当我将同一个 .exe 拖到我的 CMD 终端并按回车键时,程序 运行 没有任何问题,程序的每个功能都有效。

我附上了 pyinstaller 创建的 .spec 文件,我根本没有修改它。我真的觉得它应该工作,因为如果我从 CMD 调用它,它 100% 工作,唯一的问题是当我双击 .exe 时。非常沮丧。

同样的问题我已经在网上看到过好几次了,但没有找到对我有帮助的解决方案。任何帮助将不胜感激。

编辑:按照下面的建议,我能够让程序达到 运行。我必须更改 .spec 文件,特别是 datas 字段才能使其正常工作。但是,我现在遇到加载 .txt 文件的问题,但在编辑它们时,编辑没有按应有的方式保存。在我修复原始问题之前,所有编辑都已保存,当时我只能从 CMD 运行 程序。我在下面发布了整个脚本:

编辑 II:我没有将文件置于 'w' 模式,这就是为什么我没有得到任何输出到文本文件的原因。现在一切正常!

我的规范文件:

block_cipher = None


a = Analysis(['test.py'],
             pathex=['C:\Users\wiley\PycharmProjects\EmailBot\email_bot2'],
             binaries=[],
             datas=[('students1.txt', '.'),('students2.txt','.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='test',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=False )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='test')

我的main.py文件:

from tkinter import *
from tkinter import ttk
import re
import email_data
import smtplib
import os

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

student_view = None
email_string = ''


def display_email():
    def save_and_close():
        preview_window.destroy()

    preview_window = Toplevel()
    preview_window.title("Preview")
    preview_window.geometry('-680+300')
    preview_window.grab_set()
    preview_window.lift(root)

    preview_frame = ttk.Frame(preview_window, padding=10)
    preview = Text(preview_frame)
    close_button = Button(preview_frame, text='Close', command=save_and_close)

    preview_frame.grid()
    preview.grid(column=0, row=0, sticky='NSEW')
    close_button.grid(column=0, row=1, sticky='NSEW')

    preview.insert(END, email_string)


def format_email():
    global email_string
    email_string = email_data.email_string_raw.format(this_lab_name=t1.get(), zoom_date_time=t2.get(),
                                                      zoom_link=t3.get(),
                                                      zoom_ID=t4.get(),
                                                      zoom_passcode=t5.get(), this_lab_supplemental=t6.get(),
                                                      this_lab_consisting=t7.get(),
                                                      this_lab_due=t8.get(), file_name_tag=t9.get(),
                                                      last_lab_reminder=t10.get(),
                                                      last_lab_due=t11.get(),
                                                      last_lab_supplemental=t12.get(), last_file_name_tag=t13.get())
    view_email_button['state'] = 'normal'
    send_button['state'] = 'normal'


def send_email():
    global p, z, email_string, emails1, emails2

    def send_email_final():
        smtp_obj = smtplib.SMTP('smtp.office365.com', port=587)
        smtp_obj.starttls()
        email = email_input.get()
        password = email_pass_input.get()
        smtp_obj.login(email, password)

        from_address = email_input.get()

        msg = "Subject: CHML101: Weekly Instructional Email" + '\n\n' + email_string
        to_address_list = []
        if p.get() == 1:
            data = open(os.path.join(__location__, 'students1.txt'))
            emails = data.read()
            to_address_list = emails.split('\n')
            print(to_address_list.__str__())
        elif p.get() == 2:
            data = open(os.path.join(__location__, 'students2.txt'))
            emails = data.read()
            to_address_list = emails.split('\n')
            print(to_address_list.__str__())

        print(msg)
        smtp_obj.sendmail(from_address, to_address_list, msg)

    def confirm_normal():
        confirm_check['state'] = 'normal'

    def send_normal():
        if z.get() == 1:
            send_email_button['state'] = 'normal'
        else:
            send_email_button['state'] = 'disabled'

    send_email_window = Toplevel()
    send_email_window.title("Send Email")
    send_email_window.geometry('400x175-680+300')
    send_email_window.grab_set()
    send_email_window.lift(root)

    send_frame = ttk.Frame(send_email_window)
    email_label = Label(send_frame, text='Enter your email address:')
    pass_label = Label(send_frame, text='Enter your email password:')
    email_input = Entry(send_frame)
    email_pass_input = Entry(send_frame, show='*')
    class_label1 = Label(send_frame, text='Email class 1:')
    class_label2 = Label(send_frame, text='Email class 2:')
    class_radio1 = Radiobutton(send_frame, var=p, value=1, command=confirm_normal)
    class_radio2 = Radiobutton(send_frame, var=p, value=2, command=confirm_normal)
    confirm_label = Label(send_frame, text='Confirm selection:')
    confirm_check = Checkbutton(send_frame, state='disabled', variable=z, command=send_normal)
    send_email_button = Button(send_frame, text='Send Email', state='disabled', command=send_email_final)

    send_frame.grid(column=0, row=0, sticky='NSEW')
    email_label.grid(column=0, row=0, columnspan=2)
    pass_label.grid(column=2, row=0, columnspan=2)
    email_input.grid(column=0, row=1, columnspan=2)
    email_pass_input.grid(column=2, row=1, columnspan=2)
    class_label1.grid(column=0, row=2)
    class_label2.grid(column=2, row=2)
    class_radio1.grid(column=1, row=2)
    class_radio2.grid(column=3, row=2)
    confirm_label.grid(column=1, row=3)
    confirm_check.grid(column=2, row=3)
    send_email_button.grid(columnspan=2, column=1, row=4)


def class_list_view():
    global emails1, emails2, v, student_view

    def update_txt():
        items = student_view.get(0, 'end')
        if v.get() == 2:
            data1 = open(os.path.join(__location__, 'students2.txt'), mode='w')
            first = True
            for item in items:
                if first:
                    data1.write(item)
                    first = False
                else:
                    data1.write('\n' + item)
            data1.close()
        if v.get() == 1:
            data1 = open(os.path.join(__location__, 'students1.txt'), mode='w')
            first = True
            for item in items:
                if first:
                    data1.write(item)
                    first = False
                else:
                    data1.write('\n' + item)
            data1.close()

    def check_email():
        email = add_student_entry.get()
        if re.match(r'\w+@\w+.\w+', email) is not None:
            add_student()
            add_student_label['text'] = 'Add new student Email:'
            update_txt()
        else:
            add_student_label['text'] = 'EMAIL FORMAT INVALID'

    def delete_student():
        student_view.delete('active')
        update_txt()

    def add_student():
        if v.get() == 2:
            emails2_curr = emails2.get()
            emails2_curr = list(emails2_curr)
            emails2_curr.append(add_student_entry.get())
            emails2.set(emails2_curr)
            add_student_entry.delete(0, 'end')
        if v.get() == 1:
            emails1_curr = emails1.get()
            emails1_curr = list(emails1_curr)
            emails1_curr.append(add_student_entry.get())
            emails1.set(emails1_curr)
            add_student_entry.delete(0, 'end')

    def assign_class():
        if v.get() == 2:
            student_view['listvariable'] = emails2
        elif v.get() == 1:
            student_view['listvariable'] = emails1

    class_list = Toplevel()
    class_list.title("View/Edit Class Lists")
    class_list.geometry('400x200-680+300')
    class_list.grab_set()
    class_list.lift(root)

    student_frame = ttk.Frame(class_list)
    student_view = Listbox(student_frame, height=10, width=30)
    class1 = Radiobutton(student_frame, text='Class 1', var=v, value=1, command=assign_class)
    class2 = Radiobutton(student_frame, text='Class 2', var=v, value=2, command=assign_class)
    add_student_label = Label(student_frame, text='Add new student Email:')
    add_student_entry = Entry(student_frame, width=30)
    add_student_button = Button(student_frame, text='Add', command=check_email)
    delete_student_button = Button(student_frame, text='Delete', command=delete_student)

    add_student_entry.grid(column=2, row=1, sticky=N)
    add_student_label.grid(column=2, row=0, sticky=(N, E, W))
    add_student_button.grid(column=2, row=2)
    delete_student_button.grid(column=2, row=3)
    student_frame.grid(column=0, row=0, sticky=(N, S, E, W))
    student_view.grid(column=3, row=0, columnspan=3, rowspan=8, sticky=(N, W, S, E))
    class1.grid(column=3, row=8)
    class2.grid(column=4, row=8)


root = Tk()
root.title("Dr. Emailio Robotus")
root.geometry('600x700-670+120')
root.minsize(400, 500)

v = IntVar()
p = IntVar()
z = IntVar()

t1 = StringVar()
t2 = StringVar()
t3 = StringVar()
t4 = StringVar()
t5 = StringVar()
t6 = StringVar()
t7 = StringVar()
t8 = StringVar()
t9 = StringVar()
t10 = StringVar()
t11 = StringVar()
t12 = StringVar()
t13 = StringVar()

# data = open('students1.txt', encoding='utf-8')
data = open(os.path.join(__location__, 'students1.txt'))
emails = data.read()
emails1 = emails.split('\n')
emails1 = Variable(value=emails1)
data.close()

data = open(os.path.join(__location__, 'students2.txt'))
emails = data.read()
emails2 = emails.split('\n')
emails2 = Variable(value=emails2)
data.close()

mainframe = ttk.Frame(root, padding="5", borderwidth=5, relief='solid')

this_lab_name = ttk.Entry(mainframe, width=50, background='grey', textvariable=t1)
this_lab_name_label = Label(mainframe, text='This week\'s lab name:')

zoom_date_time = ttk.Entry(mainframe, width=50, background='grey', textvariable=t2)
zoom_date_time_label = Label(mainframe, text='This week\'s Zoom meeting (date/time):')

zoom_link = ttk.Entry(mainframe, width=50, background='grey', textvariable=t3)
zoom_link_label = Label(mainframe, text='This week\'s Zoom link:')

zoom_ID = ttk.Entry(mainframe, width=50, background='grey', textvariable=t4)
zoom_ID_label = Label(mainframe, text='This week\'s Zoom meeting ID:')

zoom_passcode = ttk.Entry(mainframe, width=50, background='grey', textvariable=t5)
zoom_passcode_label = Label(mainframe, text='This week\'s Zoom meeting passcode:')

this_lab_supplemental = ttk.Entry(mainframe, width=50, background='grey', textvariable=t6)
this_lab_supplemental_label = Label(mainframe, text='This week\'s lab\'s supplemental questions:')

this_lab_consisting = ttk.Entry(mainframe, width=50, background='grey', textvariable=t7)
this_lab_consisting_label = Label(mainframe, text='This week\'s lab should be consisting of:')

this_lab_due = ttk.Entry(mainframe, width=50, background='grey', textvariable=t8)
this_lab_due_label = Label(mainframe, text='This week\'s lab is due (date/time):')

file_name_tag = ttk.Entry(mainframe, width=50, background='grey', textvariable=t9)
file_name_tag_label = Label(mainframe, text='This week\'s lab naming format (Aspirin/Hess):')

last_lab_reminder = ttk.Entry(mainframe, width=50, background='grey', textvariable=t10)
last_lab_reminder_label = Label(mainframe, text='Last week\'s lab name:')

last_lab_due = ttk.Entry(mainframe, width=50, background='grey', textvariable=t11)
last_lab_due_label = Label(mainframe, text='Last week\'s lab is due (date/time):')

last_lab_supplemental = ttk.Entry(mainframe, width=50, background='grey', textvariable=t12)
last_lab_supplemental_label = Label(mainframe, text='Last week\'s lab\'s supplemental questions:')

last_file_name_tag = ttk.Entry(mainframe, width=50, background='grey', textvariable=t13)
last_file_name_tag_label = Label(mainframe, text='Last week\'s lab naming format (Aspirin/Hess):')

compile_button = Button(mainframe, text='Compile Email', command=format_email, width=25)
view_email_button = Button(mainframe, text='View Email', state='disabled', command=display_email, width=25)

classes_button = Button(mainframe, text='View/Modify Class List', command=class_list_view, width=18)

send_button = Button(mainframe, text='Send Email...', width=18, state='disabled', command=send_email)

mainframe.grid(column=0, row=0, sticky=(N, S, E, W))

this_lab_name.grid(column=1, row=0, sticky=E, padx=3, pady=3)
this_lab_name_label.grid(column=0, row=0, sticky=W, padx=3, pady=3)

zoom_date_time.grid(column=1, row=1, sticky=E, padx=3, pady=3)
zoom_date_time_label.grid(column=0, row=1, sticky=W, padx=3, pady=3)

zoom_link.grid(column=1, row=2, sticky=E, padx=3, pady=3)
zoom_link_label.grid(column=0, row=2, sticky=W, padx=3, pady=3)

zoom_ID.grid(column=1, row=3, sticky=E, padx=3, pady=3)
zoom_ID_label.grid(column=0, row=3, sticky=W, padx=3, pady=3)

zoom_passcode.grid(column=1, row=4, sticky=E, padx=3, pady=3)
zoom_passcode_label.grid(column=0, row=4, sticky=W, padx=3, pady=3)

this_lab_supplemental.grid(column=1, row=5, sticky=E, padx=3, pady=3)
this_lab_supplemental_label.grid(column=0, row=5, sticky=W, padx=3, pady=3)

this_lab_consisting.grid(column=1, row=6, sticky=E, padx=3, pady=3)
this_lab_consisting_label.grid(column=0, row=6, sticky=W, padx=3, pady=3)

this_lab_due.grid(column=1, row=7, sticky=E, padx=3, pady=3)
this_lab_due_label.grid(column=0, row=7, sticky=W, padx=3, pady=3)

file_name_tag.grid(column=1, row=8, sticky=E, padx=3, pady=3)
file_name_tag_label.grid(column=0, row=8, sticky=W, padx=3, pady=3)

last_lab_reminder.grid(column=1, row=9, sticky=E, padx=3, pady=3)
last_lab_reminder_label.grid(column=0, row=9, sticky=W, padx=3, pady=3)

last_lab_due.grid(column=1, row=10, sticky=E, padx=3, pady=3)
last_lab_due_label.grid(column=0, row=10, sticky=W, padx=3, pady=3)

last_lab_supplemental.grid(column=1, row=11, sticky=E, padx=3, pady=3)
last_lab_supplemental_label.grid(column=0, row=11, sticky=W, padx=3, pady=3)

last_file_name_tag.grid(column=1, row=12, sticky=E, padx=3, pady=3)
last_file_name_tag_label.grid(column=0, row=12, sticky=W, padx=3, pady=3)

compile_button.grid(column=0, row=13, columnspan=2, padx=3, pady=3)
view_email_button.grid(column=0, row=14, columnspan=2, padx=3, pady=3)
classes_button.grid(row=15, column=0, columnspan=2, padx=3, pady=3)
send_button.grid(row=16, column=0, columnspan=2, padx=3, pady=3)

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
# mainframe.rowconfigure(0, weight=1)
# mainframe.columnconfigure(0, weight=1)
# mainframe.rowconfigure(0, weight=1)
# mainframe.columnconfigure(0, weight=1)


if __name__ == '__main__':
    root.mainloop()

试试下面的 spec 文件。我刚刚将 属性 console=True 更改为 console=False 请注意,现在您需要 运行 pyinstaller main.spec 而不是 pyinstaller main.py.

如果您不想使用此规范文件,而只想从脚本中执行此操作,请在 运行 [=15] 时在命令中添加 --noconsole--windowed =].

例如pyinstaller main.py --noconsole.

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['__main__.py'],
             pathex=['C:\Users\wiley\PycharmProjects\EmailBot\email_bot'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='__main__',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=False)
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='__main__')

按照给出的建议,我能够使程序达到 运行。我必须更改 .spec 文件,特别是数据字段才能使其正常工作。

然而,我当时遇到了一个问题,即 .txt 文件将加载到程序中,但在编辑它们时,编辑没有按应有的方式保存。解决方案:我没有将文件置于 'w' 模式,这就是我没有得到任何输出到文本文件的原因。现在一切正常!感谢大家的帮助。我已经更新了上面的文件以反映最终的工作版本