PyInstaller y el módulo python-docx no funcionan juntos

Estoy tratando de hacer un ejecutable de mi progtwig para dar a mi equipo FTC. Todo funciona, pero cuando bash usar mi script que incluye python-docx en él pero no lo completa todo. Funciona cuando lo ejecuto en PyCharm y desde la terminal. Aquí está el código. Tengo python3.

from tkinter import * import sys,math,random,datetime,os,time import tkinter.messagebox from tkinter import filedialog from tkinter.filedialog import askopenfilename from tkinter.messagebox import showerror from time import gmtime, strftime from docx import Document from docx.shared import Inches import xlsxwriter export = "Excel" job = "No Job" current_time = strftime("%m-%d-%Y", gmtime()) root = Tk() TextArea = Text(width=60,height=17,pady=0) task = Entry(width=90) task.insert(10, "Task:") e1 = Entry() e1.insert(10, "First Name") e2 = Entry() e2.insert(10, "Last Name") TextArea.insert(END, "Reflection:") title = ["Titan Tech ", "Caleb Fahlgren made this!", "Python is life!", "FIRST Robotics!","This program is over 200 lines of code!"] title = (random.choice(title)) root.title(title) root.geometry("680x600") #Submit Button #This definition writes to the excel file def Submit(): submit = tkinter.messagebox.askquestion("Submit Entry", "Are you sure you want to submit?") if submit == "yes": current_time = strftime("%m-%d-%Y %H:%M", gmtime()) fullname = "%s %s" % (e1.get(), e2.get()) lastname = "%s" % (e2.get()) task1 = "%s" % (task.get()) alltext = TextArea.get("1.0",END) workbook = xlsxwriter.Workbook('Titan Tech ' + (strftime("%m-%d-%Y", gmtime())) + '.xlsx') worksheet = workbook.add_worksheet() format_text = workbook.add_format() format_text.set_text_wrap() cell_format = workbook.add_format({'align': 'center','valign': 'vcenter','border': 1,'text_wrap': 1}) middle = workbook.add_format({'align':'center'}) worksheet.merge_range('A5:G20', "", cell_format) worksheet.merge_range('A4:G4', "", cell_format) bold = workbook.add_format({'bold': 1}) worksheet.write('A1', 'Name:',bold) worksheet.write('A4', task1) worksheet.write_string('B1',fullname, bold) worksheet.merge_range('A2:B2', "", cell_format) worksheet.merge_range('D2:E2', "", cell_format) worksheet.write_string('A2',"Student Initials") worksheet.write_string('C2',"_______",middle) worksheet.write_string('D2',"Mentor Initials") worksheet.write_string('F2',"_______",middle) worksheet.write('E1', 'Date:',bold) worksheet.write('F1',(strftime("%m-%d-%Y", gmtime())),bold) worksheet.write_rich_string('A5',alltext ,cell_format) userconfirm = tkinter.messagebox.showinfo("Save","Your entry has been saved to an " + export + " document!") workbook.close() def Reset(): python = sys.executable os.execl(python, python, * sys.argv) def keypress(event): if event.keysym == 'Escape': root.destroy() def Quit(): quitask = tkinter.messagebox.askquestion("Quit", "Are you sure you want to quit?") if quitask == "yes": root.destroy() firstname = Label(root, text="First Name",font=("Helvetica", 12),fg="green") lastname = Label(root, text="Last Name",font=("Helvetica", 12),fg="green") time = Label(root, text=current_time, font=("Helvetica", 12),fg="black") ScrollBar = Scrollbar(root) ScrollBar.config(command=TextArea.yview) TextArea.config(yscrollcommand=ScrollBar.set) ScrollBar.pack(side=RIGHT, fill=Y) def cf(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 1") def al(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 2") def cm(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 3") def np(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 4") def cp(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 5") def ns(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 6") def ct(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 7") def kt(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 8") def mt(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 9") def ek(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Sample") e2.insert(10, "Name 10") def n(): e1.delete(0, 'end') e2.delete(0, 'end') e1.insert(10, "Team") e2.insert(10, "Name") def other(): e1.delete(0, 'end') e2.delete(0, 'end') def TextFile(): current_time = strftime("%m-%d-%Y", gmtime()) fullname = "%s %s" % (e1.get(), e2.get()) lastname = "%s" % (e2.get()) task1 = "%s" % (task.get()) alltext = TextArea.get("1.0",END) textfile1 = tkinter.messagebox.askquestion("Text File", "Are you sure you want to export as a text file?") if textfile1 == "yes": textfile = open('Titan Tech' + (strftime("%m-%d-%Y", gmtime())) + '.txt',"w") textfile.write("Titan Tech | Team # 10385 ") textfile.write("Name: " + fullname) textfile.write(" " + "Date: " + current_time) textfile.write('\n' + '\n' + task1) textfile.write('\n' + '\n' + alltext) textfile.close() tkinter.messagebox.showinfo("Save", "You have exported to text file successfully. It is in the location of this program.") def helpmenusave(): helpsaveconfirm = tkinter.messagebox.showinfo("Save", "This program exports the Excel, World, or text document to the location of this program!") def userinterfacemenu(): helpuserinterface = tkinter.messagebox.showinfo("User Interface", "The Users tab is where you can click on your name to autofill the name text boxes. The Export tab is where you choose to export to a specific format.") def Open(): textopen = tkinter.filedialog.askopenfile(mode='r', filetypes=[('Text Files', '*.txt'),('All Files', '*')]) if textopen != None: txtopen = textopen.read() TextArea.delete(1.0,END) TextArea.insert(END,txtopen) tkinter.messagebox.showinfo("Open", "Success!") try: txtopen.close() except AttributeError: print("Attribute Error") menubar = Menu(root) filemenu = Menu(menubar,tearoff = 0) filemenu.add_command(label="New",command=Reset) filemenu.add_command(label="Open",command=Open) filemenu.add_command(label="Exit",command=Quit) menubar.add_cascade(label="File",menu=filemenu) #help menu helpmenu = Menu(menubar,tearoff = 0) helpmenu.add_command(label="None", command=n) helpmenu.add_command(label="Sample Name 1", command=cf) helpmenu.add_command(label="Sample Name 2", command=al) helpmenu.add_command(label="Sample Name 3", command=cm) helpmenu.add_command(label="Sample Name 4", command=np) helpmenu.add_command(label="Sample Name 5",command=cp) helpmenu.add_command(label="Sample Name 6",command=ns) helpmenu.add_command(label="Sample Name 7",command=ct) helpmenu.add_command(label="Sample Name 8",command=kt) helpmenu.add_command(label="Sample Name 9",command=mt) helpmenu.add_command(label="Sample Name 10", command=ek) helpmenu.add_command(label="Other", command=other) menubar.add_cascade(label="Users",menu=helpmenu) 

Aquí es donde está el problema. Funciona en Pycharm y en terminal, pero cuando lo compilo con PyInstaller solo hace la línea wordsaveask = tkinter.messagebox.askquestion pero no hay nada debajo. Se supone que crea el archivo de Word pero no lo hace. Tampoco recibo ningún mensaje de error.

 def Word(): current_time = strftime("%m-%d-%Y", gmtime()) lastname = "%s" % (e2.get()) fullname = "%s %s" % (e1.get(), e2.get()) task1 = "%s" % (task.get()) alltext = TextArea.get("1.0",END) wordsaveask = tkinter.messagebox.askquestion("Save", "Are you sure you want to export to a Microsoft Word file?") if wordsaveask == ("yes") : document = Document() document.add_heading('FTC Titan Tech Summary', 0) document.add_paragraph('Titan Tech | Team # 10385') document.add_paragraph('Mentor Initials ____ Student Initials _____') document.add_paragraph('Name: ' + fullname) document.add_paragraph('Date: ' + current_time) document.add_paragraph(task1) document.add_paragraph(alltext) document.save('Titan Tech ' + (strftime("%m-%d-%Y", gmtime())) + '.docx') tkinter.messagebox.showinfo('Save', 'The program has exported the information to a Microsoft Word document!') #export exportmenu = Menu(menubar, tearoff = 0) exportmenu.add_command(label="Microsoft Excel",command=Submit) exportmenu.add_command(label="Microsoft Word",command=Word) exportmenu.add_command(label="Text File",command=TextFile) menubar.add_cascade(label="Export",menu=exportmenu) helpmenu = Menu(menubar, tearoff = 0) helpmenu.add_command(label="Save Help", command=helpmenusave) helpmenu.add_command(label="User Interface", command=userinterfacemenu) menubar.add_cascade(label="Help",menu=helpmenu) root.config(menu=menubar) Submit = Button(root, fg="white", bg="green", text="Submit", width=50, command=Submit, activebackground="yellow") Quit = Button(root, fg="white", bg="green", text="Quit", width=50, command=Quit,activebackground="yellow") root.bind_all('', keypress) firstname.pack() e1.pack() lastname.pack() e2.pack() time.pack() task.pack() TextArea.pack(expand=YES, fill=BOTH) Submit.pack() Quit.pack() mainloop() 

Pyinstaller no incluye módulos docx (tuve el mismo problema, lo escribiré para otros porque no pude encontrar el tutorial adecuado sobre cómo solucionarlo)

Si tiene instalado Pyinstaller use en cmd:

 pyi-makespec your_py_file_name.py 

Este comando crea el archivo .spec pero no continúa con la comstackción del ejecutable.

Abra el archivo .spec en el Bloc de notas y edítelo agregando:

 import sys from os import path site_packages = next(p for p in sys.path if 'site-packages' in p) 

Y

 datas=[(path.join(site_packages,"docx","templates"), "docx/templates")], 

Mi ejemplo de archivo .spec se ve así

 # -*- mode: python -*- import sys from os import path site_packages = next(p for p in sys.path if 'site-packages' in p) block_cipher = None a = Analysis(['xml_reader.py'], pathex=['C:\\Users\\Lenovo\\Desktop\\exe'], binaries=[], datas=[(path.join(site_packages,"docx","templates"), "docx/templates")], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True, name='xml_reader', debug=False, strip=False, upx=True, console=True ) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='xml_reader') 

Para hacer el tipo de archivo exe en cmd

 pyinstaller your_py_file_name.spec 

Debería producir la carpeta dist donde se encuentra su ejecutable.

Ok, primero vamos a trabajar con el Ejemplo Verificable Mínimo , ¿de acuerdo?

 from tkinter import * import tkinter.messagebox root = Tk() def Word(): wordsaveask = tkinter.messagebox.askquestion("Save", "do you want to save?") if wordsaveask == ("yes"): with open('Titan Tech.docx',"w") as f: f.write("TEST") tkinter.messagebox.showinfo('Saved', 'The file was made') else: tkinter.messagebox.showinfo("ok","did not save") button = Button(root,text="test",command=Word) button.pack() mainloop() 

Esto funciona bien en el terminal, pero misteriosamente no llega al mensaje guardado con éxito cuando se abre después de empaquetarlo en una aplicación.

Usted dijo que no recibe ningún mensaje de error, pero sin un terminal o un raise TypeError sería invisible para usted, así que pongamos algo en su lugar para redirigir el mensaje:

 from tkinter import * import tkinter.messagebox root = Tk() def Word(): try: #SOMETHING HERE IS GOING WRONG wordsaveask = tkinter.messagebox.askquestion("Save", "Are you sure you want to export to a Microsoft Word file?") if wordsaveask == ("yes"): with open('Titan Tech.docx',"w") as f: f.write("TEST") tkinter.messagebox.showinfo('Save', 'The program has exported the information to a Microsoft Word document!') else: tkinter.messagebox.showinfo("ok","did not save") except: import traceback tkinter.messagebox.showinfo("ERROR",traceback.format_exc()) raise # Errors should never pass silently. - The Zen of Python, by Tim Peters button = Button(root,text="test",command=Word) button.pack() mainloop() 

una vez que corro esto me sale esta pequeña ventana emergente útil: mago de rastreo, el texto está directamente debajo

 Traceback (most recent call last): File "/Users/Tadhg/Documents/codes/test.app/Contents/Resources/main.py", line 10, in Word with open('Titan Tech.docx',"w") as f: PermissionError: [Errno 13] Permission denied: 'Titan Tech.docx' 

Ahora sí, estoy usando un mac y no estoy usando PyInstaller (hice mi propio PyInstaller aplicaciones con código Python puro) pero sigo pensando que esta es una respuesta válida porque le dirá cómo proceder con la depuración. Si publica el mensaje de error que recibe, estaré encantado de ayudarle.