PyInstaller executable doesn't show GUI - python-3.x

I'm currently working on a program that accepts a specific file as input, works on the data and provides two graphs through Matplotlib (the only module imported in the data parsing file).
For this I have made a small GUI for the user to choose the file to have a graph made of. (w/ tkinter and PIL imported).
I have to make an app out of this and I'm using PyInstaller to it. Unfortunately I haven't been able to make the final file work (or run properly).
I have already made several modifications either to the code itself, but also to the PyInstaller's .spec file.
I have added the function to fix the path for PyInstaller.
I have modified the .spec file to add the path to an image, not to show the console.
I have tried with these settings both on/off: UPX, One File.
I have checked the log files for missing modules as everything seems to be ok.
Some of the code:
Imports on the GUI file:
import sys
import os
import tkinter as tk
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showerror
from PIL import ImageTk, Image
import rectifierDataParser
Imports on the Data Parsing file:
import sys
import os
import matplotlib
matplotlib.use("TkAgg")
from matplotlib import pyplot as plt
GUI File:
class Application(tk.Frame):
def __init__(self, master = None):
tk.Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
self.fileButton = tk.Button(self, text(...))
self.quitButton = tk.Button(self, text(...))
self.fileButton.pack(side = 'top')
self.quitButton.pack(side = 'bottom')
def load_file(self):
filename = askopenfilename(title = "Select file", filetypes = [("Files", ("*.001", (...)))]
rectifierDataParser.main(filename)
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
app = Application()
app.master.title('Graphing Data')
app.master.geometry('300x200')
img = ImageTk.PhotoImage(Image.open("logo.jpg"))
panel = tk.Label(app, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
app.mainloop()
As I'm currently not able to see the GUI on the screen, is there any problem with the code itself or any compatibility with PyInstaller (supposedly PyInstaller is fully functional w/Tkinter).
I hope one of you might help me have a breakthrough as I have been stuck on this for way to much time! Many thanks in advance!

There is a few issues with the tcl version that comes with python, discussed here. I've written an script that automatically changes the init.tcl file to the correct version.
N.B. you shouldn't use the --onefile flag as the file directories aren't present, and the script won't work.
cd /path/of/your/app
git clone https://github.com/jacob-brown/TCLChanger.git
pyinstaller --windowed app.py
python TCLChanger/TCLChanger.py
You should now be able to open your app, from the terminal and via double clicking.

I was having exactly the same problem and I fixed it by editing the .spec file.
I had to set
console=True
You'll find this option in the bottom of your .spec file.
Something like this:
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='YOU/EXECUTABLE/NAME',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True)
If you do not find your .spec file you can generate one by running
pyi-makespec yourprogram.py

Related

How can I resolve a python3 ModuleNotFoundError in thonny when importing from a subfolder of my project folder

I began developing my python3 application in a single source file, called main.py, but then began to implement sub-windows as classes and moved each class into a separate source file in the Classes subdirectory. The application ran fine as a single source file, but now with all the imports, it is not able to run, due to missing module errors. I want to resolve these errors so that the application can run with the new project directory hierarchy, making it possible to create parallel projects that make use of my Classes library.
I expect my application to run without generating errors.
I'm getting the following message in thonny Assistant when I run main.py:
ModuleNotFoundError: No module named 'ToplevelWindow'
python_backend.py, line 314
However, when I run CalibrationWindow.py in thonny, it shows:
The code in CalibrationWindow.py looks good.
Also, when I run ToplevelWindow.py in thonny, it shows:
The code in ToplevelWindow.py looks good.
I'm using thonny 3.3.10 via ssh hosted by a Raspberry Pi running raspbian buster and python 3.7.3.
My project directory structure is as follows:
gui
\
__init.py__
main.py
Classes
\
__init__.py
CalibrationWindow.py
ToplevelWindow.py
I added the empty __init__.py files, created in nano, in order to try to get the imports working, but have not noticed any improvement.
The source file essential contents are as follows:
# File: main.py
from tkinter import *
import tkinter.ttk as ttk
from Classes.CalibrationWindow import CalibrationWindow
def OpenCalibrationWindow():
CalibrationWindow()
# File: ToplevelWindow.py
import tkinter as tk
class ToplevelWindow():
def __init__(self, title, geometry):
self.window = tk.Tk()
#...
if __name__ == 'main':
obj = ToplevelWindow('Test ToplevelWindow', '600x400')
# File: CalibrationWindow.py
from ToplevelWindow import ToplevelWindow
from tkinter import *
class CalibrationWindow(ToplevelWindow):
def __init__(self, windowTitle, windowGeometry):
super().__init__(windowTitle, windowGeometry)
#...
if __name__ == 'main':
obj = CalibrationWindow('Test CalibrationWindow', '600x400')
The error only seems to appear when a source file within the Classes folder imports from another source file within the Classes folder.
I don't know where to find sys.path or how to set that up, so I don't think I have set up the project correctly for all imports to work right, but it seems the first level of imports is working and it's only the last level where it is going wrong.

cx_Freeze .app crashes when external import is used (mac OS monterey)

I have a problem freezing my tkinter application. As long as I don't import an external library the frozen app works. If I import a module like pandas the app crashes with no error messages. My OS is macOS monterey, I also tried on a windows machine and the same problem happens. Here's an example code:
from tkinter import *
import pandas as pd # it only works after building if this line is ommited
class MyApp(Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("Welcome to My_App")
self.geometry('350x200')
app = MyApp()
app.mainloop()```
It seems there is a problem with the conda environment and there is somehow a clash between the conda env and cx_Freeze. It was solved when I created a pyenv.

Create executable with python 3.7 PyQt5 and cx_Freeze but DLL Failed to load

I developed a "not so simple" GUI with PyQt5 via Anaconda 3 (Python 3.7) and Designer.
I have 3 different .ui files that I import in my program.
When I run cx_Freeze, everything runs good, I create the .exe. Then, I copy the "platform" folder from my "Python" folder in the "Build" folder that cx_Freeze creates.
BUT, when I pass it to an other machine without anything on it (no anaconda, no python, no cx_Freeze, nothing), the app doesn't run. I get:
ImportError: DLL load failed: The specified module could not be found
It happens in the 10th line of my code which is:
from PyQt5 import QtGui, QtWidgets
The imports in my code are:
from PyQt5 import QtGui, QtWidgets
import sys
import glob
import datetime
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import design
import flex
import entry
design, flex and entry are the .ui files. They all contain this part at the end (don't know if it helps):
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
And finally, the setup file I run with cx_Freeze:
import sys
from cx_Freeze import setup, Executable
import matplotlib
import numpy
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": ["os", "matplotlib"], "includes": ["PyQt5", "atexit"], "excludes": ["tkinter"]}
# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup( name = "Flexicounts",
version = "0.1",
description = "Flexicounts pour faire tes comptes facilement",
options = {"build_exe": build_exe_options},
executables = [Executable("flexicounts.py", base=base)])
I read a lot about it, but I feel that there is no "miracle" solution...
Could you help me freeze my app and make it run on a "virgin machine" ?
You might be facing Issue #504 of the cx_Freeze repository. In that case, quoting a comment by marceloduarte there:
The workaround is to copy python3.dll to the directory where the executable was made. cx_Freeze copies python37.dll, but does not copy python3.dll. The vcruntime140.dll may also have to be copied when it no longer exists on the system.
First try to manually copy these DLLs (you find them in the directory of your python installation containing python.exe) to the directory of your executable. If that solves the problem, you can tell cx_Freeze to do it for you by using the include_files list of the build_exe_options. Modify you setup script as follows:
import os
python_dir = os.path.dirname(sys.executable) # directory of your python installation
build_exe_options = {"packages": ["os", "matplotlib"],
"includes": ["PyQt5", "atexit"],
"include_files": [os.path.join(python_dir, "python3.dll"), os.path.join(python_dir, "vcruntime140.dll")],
"excludes": ["tkinter"]}
Maybe you need to copy further DLLs, such as msvcp140.dll, or any other DLL present inside the site-packages/PyQt5 directory (including subdirectories) of your Python installation.
I faced a similar problem recently, with the following versions:
python 3.6.6 x64
cx-Freeze==6.10
PyQt5==5.15.4
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.0
PyQt5-stubs==5.15.2.0
PyQtWebEngine==5.15.5
PyQtWebEngine-Qt5==5.15.2
Symptoms :
The cx_Freeze package was successful and execution working fine on my machine, because (as I found later and explained below) I had Python 3.6 x64 installed on my machine and visibile via environement variables.
On an another machine, the package failed with the exact same error on first PyQt5 import:
ImportError: DLL load failed: The specified module could not be found
However, in my case, all the necessary dlls seemed all in the right place :
cx_Freeze seemed to have correctly put python3.dll and python36.dll next to the executable. But no other dll were copied there (no vcruntime140.dll for instance)
all the necessary python modules were in place, including PyQt5 and all its dlls
Solution that was working :
(I created a cx_Freeze issue)
Contrary to the other answer, I had to copy
python3.dll
(either from <cx_freeze_build_dir_target> or from python3.6.6 install dir ...)
(python36.dll works too but is much bigger)
into the following folders:
<cx_freeze_build_dir_target>/lib/PyQt5/
The corresponding cx_Freeze setup config for this would be to add this to the include_files list, in the following fashion.
Unfortunatly, this does not work due to cx_Freeze having an sort of exception file liste that includes python3.dll and prevents the actual copy via include_files. So, the copy should be performed manually, after full setup script execution...
# import pkgutil
from pathlib import Path
from glob import glob
import sys
# ... your stuff
#
includes_list = []
# your stuff
# ...
# pyqt5 force copy of pythonlib(s) into qt5 target dir
# may not work if you intend to zip pyqt5 ?
python_dir = Path(sys.executable).parent
python_dlls = [ Path(p) for p in glob(f"{python_dir.as_posix()}/python*.dll")]
pyqt_base_dir = Path("lib", "PyQt5")
# prepare cx_Freeze tuples (source file, target dir)
includes_list+= [ (p, pyqt_base_dir / p.name) for p in python_dlls ]
build_exe_options = {"packages" : ..., # your packages
"includes" : ..., # yours
"include_files": includes_list,
"excludes" : ... # yours
}

Can't open Pyinstaller's output file

SOLUTION:
The main issue was occurring due to ImageTk , this can be skipped by loading image using tkinter instead of PIL.ImageTk by using this command and using this object as normal you would do with PIL.ImageTk.
my_image = PhotoImage(file ="Image location here")
MAIN ISSUE:
I'm trying to pack these files into a single executable file using pyinstaller, but after compilation, the executable file doesn't run, don't know where the error is, files in the given link, and installation log in pictures
Command Used:
pyinstaller --onefile ui.py
Where ui.py is my driver script
Files:
https://github.com/RoyalEagle73/NIT-JSR-Result-Leecher/tree/master/GUI%20%2B%20Source%20v2.0/Source
Build Log( Images ):
What I've already tried
tried Cx_Freeze as an alternative but no application seems to open the output file.
here is what I'm importing overall in the whole program
from tkinter import *
from PIL import ImageTk, Image
import fb
from tkinter.ttk import Progressbar
import webbrowser
from tkinter import messagebox
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
from bs4 import BeautifulSoup
import time
I was not able to access the github link in your question, I think it did not get pasted properly. So I am unable to access your source files.
Try one of these:
pyinstaller --onefile --noupx ui.py
or
pyinstaller --debug --onefile --noupx ui.py
The pyinstaller uses UPX. The documentation for pyinstaller states the following:
PyInstaller looks for UPX on the execution path or the path specified
with the --upx-dir option. If UPX exists, PyInstaller applies it to
the final executable, unless the --noupx option was given. UPX has
been used with PyInstaller output often, usually with no problems.
Hope this helps.

In exe built by cx_Freeze, "asksaveasfile" and "askopenfile" are not working.

I have two built in buttons dedicated for browsing and saving the output. Its working fine in console. But when I built exe out of it, the two buttons simply do not open the explorer in order to browse or save.
Here is the cx_freeze code
import cx_Freeze
import sys
base = None
if sys.platform == 'win32':
base = "Win32GUI"
executables = [cx_Freeze.Executable("cypher.py", base=base,icon="icon2.ico")]
cx_Freeze.setup(
name = "Classical-Cypher",
options = {"build_exe": {"packages":["tkinter","PIL"], "include_files":["icon2.ico"]}},
version = "BETA",
description = "Encryption and decryption of classical cyphers",
executables = executables
)
Building shows no error!
The image of the GUI is GUI
Please help.
Yeah, I sort this out!
I have used the following in the original script
import tkinter
import tkinter.filedialog
And in the cx_Freeze script,
options = {"build_exe": {"packages":["tkinter","PIL","tkinter.filedialog"], "include_files":["icon2.ico"]}},
Done ! :)

Resources