cx_freeze Error: Module not found tkinter - python

I started having some issues with miniconda and PyCharm so I had to reinstall them. However, now when I use cx_freeze to create .exe I get the error below.
Here is my code:
from tkinter import *
from tkinter import ttk
from ttkthemes import ThemedTk
from ttkthemes import themed_tk as tk
import os
from tkinter import messagebox
import getpass
import pyodbc
import test
import time
class Application(object):
def __init__(self,master):
self.master=master
self.itemIn = ttk.Button(master, text="In", width=35,
command=self.itemIn).grid(row=2, column=0, padx=10,pady=15)
self.itemOut = ttk.Button(master, text="Out", width=35,
command=self.itemOut).grid(row=3, column=0, padx=10)
def itemIn(self):
pass
def itemOut(self):
pass
def main():
global userList
strForDB = os.getcwd() + '\DBINFO.txt'
openDBFile = open(strForDB, 'r')
currentDirForDB = openDBFile.read()
openDBFile.close()
dbPath = currentDirForDB
conToSubmit = pyodbc.connect(dbPath)
curToSubmit = conToSubmit.cursor()
userName = getpass.getuser()
root = tk.ThemedTk()
root.get_themes()
root.set_theme("radiance")
app=Application(root)
root.title("Main Menu v:5.1")
root.configure(background="#F4F3F1")
root.resizable(0, 0)
# Change Application Icon with below:
root.wm_iconbitmap(os.getcwd()+'/Z Logo.ico')
### To maximize
# w, h = root.winfo_screenwidth(), root.winfo_screenheight()
# root.geometry("%dx%d+0+0" % (w, h))
root.geometry('340x510+300+80')
root.mainloop()
#else:
# messagebox.showerror("Access Denied", "You are not allowed to access this application.")
# return
if __name__=='__main__':
main()
This is cx_freeze build script, where I have imported all the relevant modules.
import cx_Freeze
import os
from cx_Freeze import *
import sys
if sys.platform == "win32":
base = "Win32GUI"
imodules=['tkinter','pyodbc','getpass','pathlib','openpyxl','datetime','os','win32print','win32ui'] #modules to include
emodules=[] ###modules to NOT include
#(useful if a module is forcefully installed
#even if you don't want that module)
build_exe_options={"packages":imodules,"excludes":emodules}
setup(
name= "WMS System",
options={"build_exe":build_exe_options},description="App to track Inventory",author="VM",
executables=[
Executable(
"WMS.py", base=base, icon="Z logo.ico"
)
]
)
I have been using cx_freeze for quite some time but I have never seen this error.

I was having identical problem as you and after a long troubleshooting session I found out that
in /lib folder of my build i had "Tkinter" folder, renaming it to "tkinter" solved the above issue
any following errors of the type module not found could be solved by either adding them to the "includes" tag of build options or finding and copying the whole module folder yourself from python installation folder

The folder name in project must be "lib/tkinter", but maybe it is "lib/Tkinter", then you must rename the folder from "Tkinter" to "tkinter".

Related

How to open a tkinter window that is in an other file in Python?

I recently started working on a program in python using Tkinter and now I want to open it from another file.
I have a home page file named HomePage.py that will have a button to open another file, called VirusTotalAPI.py. I didn't find any answers because when I run the program, it opens the VirusTotalAPI.py file, and if I close it the Homepage.py will run, but the button won't work and if I try to close it, it will open the HomePage.py.
#Homepage.py
from tkinter import *
import VirusTotalAPI as vt
Home_Window=Tk()
Home_Window.geometry("980x530")
Home_Window.title("VirusTotal By Carotide")
Home_Window.config(background="grey")
def Window_35_mo() :
vt.Window_35mo
Window_35_mo_open = Button()
Window_35_mo_open.config(text= "Fichier < 35 mo", command= Window_35_mo)
Window_35_mo_open.pack()
Home_Window.mainloop()
The next one is a part from the VirusTotalAPI.py because the file is too long
#VirusTotalAPI.py
import requests
import hashlib
import json
from tkinter import *
from tkinter import filedialog
import HomePage
Window_35mo = Tk()
Window_35mo.geometry("980x530")
Window_35mo.title("VirusTotal By Carotide")
Window_35mo.config(background="grey")
global files
global file_path
def retrieve_API():
API_Value=GetAPIBox.get("1.0","end-1c")
print(API_Value)
GetAPIBox=Text(Window_35mo, height=2, width=10)
GetAPIBox.pack()
API_Button=Button(Window_35mo, height=1, width=10, text="YourAPI",
command=lambda: retrieve_API())
API_Button.pack()
Window_35mo.mainloop()
Thank you in advance.
I tried to import it by different ways like this:
import VirusTotalAPI
Or this:
from VirusTotalAPI import *
I tried to do this too:
from tkinter import *
from VirusTotalAPI import Window_35mo
Home_Window=Tk()
Home_Window.geometry("980x530")
Home_Window.title("VirusTotal By Carotide")
Home_Window.config(background="grey")
#homepage
def winopen35mo() :
Window_35mo
Window_35_mo_open = Button()
Window_35_mo_open.config(text= "Fichier < 35 mo", command= winopen35mo)
Window_35_mo_open.pack()
Home_Window.mainloop()
And it told me this:
ImportError: cannot import name 'Window_35mo' from partially initialized module 'VirusTotalAPI' (most likely due to a circular import)
I finally found how to do it there is the solution :
First we need to import os, subprocess and sys
from tkinter import *
import os
import subprocess
import sys
Then,we declare the file path of the file, for this one it is VirusTotalAPI.py by doing so :
GUI_VirusTotalAPI_Path = 'C:\\Users\\...\\VirusTotalAPI.py'
Now we enter the args, to execute and enter the path name :
args = '"%s" "%s" "%s"' % (sys.executable,
GUI_VirusTotalAPI_Path,
os.path.basename(VirusTotalAPI))
We are almost there, now we create a function to run this using the args we previoulsy used :
def Open_GUI_VirusTotalAPI_35mo() :
proc = subprocess.run(args)
Then another function to destroy the window :
def DestroyHomeWindow() :
Home_Window.destroy
Finally we create the button and "tell" it to execute the command Open_GUI_VirusTotalAPI_35moand at the same time close the window :
Window_35_mo_open = Button()
Window_35_mo_open.config(text= "Fichier < 35 mo", command= lambda:[Home_Window.destroy(),Open_GUI_VirusTotalAPI_35mo()])
Window_35_mo_open.pack()
And this is how I did it, sorry for the poor explanation and my bad english, hope this helped some people.

cx_freeze debugging console?

I try to build my (fine working) python 3.6 tkinter gui app to a windows excecutable. After hours of trial an error (with some name and dll issues) I got it to run. But it seems to have varoius of bugs. Some functions seem not to work and I have no console output of the produced error... is there a way to debug the exe?
this is my setup.py
import sys
from cx_Freeze import setup, Executable
import os
os.environ['TCL_LIBRARY'] = r'C:\Users\xxx\AppData\Local\Programs\Python\Python36\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Users\xxx\AppData\Local\Programs\Python\Python36\tcl\tk8.6'
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
executables = [
Executable('myApp.py', base=base)
]
build_exe_options = {"packages": ["tkinter",
"PIL",
"savReaderWriter",
"numpy",
"scipy",
"os"],
"include_files": ["tcl86t.dll",
"tk86t.dll"]}
setup(name='myApp',
version='0.1',
description='some description',
options = {'build_exe': build_exe_options},
executables=executables
)
myApp.py
is too big to post it here. This is a snippet that only works 'unfreezed'. You need an spss.sav file like this to try this out.
from tkinter import *
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk, ImageDraw
from savReaderWriter import SavReader
import numpy as np
from scipy.ndimage import gaussian_filter
import os
class MyApp:
spss_file = None
def import_spss(self, *args):
filename = filedialog.askopenfilename()
if filename:
try:
with SavReader(filename, returnHeader=True, ioUtf8=True) as reader:
spss_file = reader.all()
self.spss_file = np.array(spss_file)
except Exception as ex:
messagebox.showinfo(title="Import SPSS File",
message="Warning: wrong file format chosen! \nAccepted formats: sav")
print(ex)
return
else:
return
def main():
App = MyApp()
App.import_spss()
print("everything works fine")
main()
if you want the console window to appear, after it is frozen, just remove this code from the setup script:
if sys.platform == 'win32':
base = 'Win32GUI'
what that code does is it tells cx_Freeze to have the console window not show up, after frozen. this is only required on windows, because on other OSes,it depends on whether or not it was run from a terminal. make sure though, when you have finished debugging it, to put that code back in, or the console window will show up in your app.
by the way, one of the most annoying problems I've ever had was when making a program with tkinter and cx_Freeze. the problem was that it was starting in the wrong directory and not able to find the TK Dll. If when you run this with the console, and you see something about a file not found, chances are you are not including it or it is in the wrong directory.
have a good day!

Python tkinter.filedialog askfolder interfering with clr

I'm mainly working in Spyder, building scripts that required a pop-up folder or file Browse window.
The code below works perfect in spyder.
In Pycharm, the askopenfilename working well, while askdirectory do nothing (stuck).
But, if running in debug mode - the script works well.
I tried to run the script from SAS jsl - same issue.
Any Idea what should I do?
Python 3.6
Pycharm 2017.2
Thanks.
The Code I'm using includes:
import clr #pythonnet 2.3.0
import os
import tkinter as tk
from tkinter.filedialog import (askdirectory,askopenfilename)
root = tk.Tk()
root.withdraw()
PPath=askdirectory(title="Please select your installation folder location", initialdir=r"C:\Program Files\\")
t="Please select jdk file"
if os.path.exists(os.path.expanduser('~\Documents')):
FFile = askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t, initialdir=os.path.expanduser('~\Documents'))
else:
FFile= askopenfilename(filetypes=(("jdk file", "*.jdk"),("All Files", "*.*")),title=t)
sys.path.append(marsDllPath)
a = clr.AddReference('MatlabFunctions')
aObj = a.CreateInstance('Example.MatlabFunctions.MatLabFunctions')
edit: seems like issue related to the pythonnet "imoprt clr", but I do need it in the code.
Similar question asked here: https://github.com/pythonnet/pythonnet/issues/648
Your problem is rather mediocre, although not so obvious. The problem is not in tinker or pythonnet, it stems from the COM threading model.
To begin with, since you're using the clr, let's try to use dialogs directly with it (it's not absolutely necessary to import the tinker module):
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
# clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# creating instances of dialogs
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
# try to show any of them
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
As you can see, it hangs just like in your case. The reason, as was mentioned above, stems from the threading's apartment state([1], [2]).
Therefore the clr implicilty sets this state to MTA (Multi-threaded apartment), which can be tested via CoGetApartmentType function:
# importing ctypes stuff
import ctypes
get_apartment = ctypes.windll.ole32.CoGetApartmentType
# comment/uncomment this import to see the difference
# import clr
apt_type = ctypes.c_uint(0)
apt_qualifier = ctypes.c_uint(0)
if get_apartment(ctypes.byref(apt_type), ctypes.byref(apt_qualifier)) == 0:
# APPTYPE enum: https://msdn.microsoft.com/en-us/library/windows/desktop/ms693793(v=vs.85).aspx
# APTTYPEQUALIFIER enum: https://msdn.microsoft.com/en-us/library/windows/desktop/dd542638(v=vs.85).aspx
print('APTTYPE = %d\tAPTTYPEQUALIFIER = %d' % (apt_type.value, apt_qualifier.value))
else:
print('COM model not initialized!')
However, many older COM objects, such as shell dialogs, require STA mode.
Good explanation about the difference between those two states can be found here or there.
Finally, the solutions:
1) Use STA thread for dialogs:
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# importing pythonnet
import clr
# adding reference (if necessary) to WinForms and importing dialogs
#clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import OpenFileDialog, FolderBrowserDialog
# adding reference (if necessary) to Threading and importing Thread functionality
#clr.AddReference('System.Threading')
from System.Threading import Thread, ThreadStart, ApartmentState
# WinForms thread function example
def dialog_thread():
folder_dialog = FolderBrowserDialog()
file_dialog = OpenFileDialog()
folder_dialog.ShowDialog()
file_dialog.ShowDialog()
# Tk thread function example
def tk_dialog_thread():
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
# check again apartment state at start
current_state = Thread.CurrentThread.GetApartmentState()
if current_state == ApartmentState.STA:
print('Current state: STA')
elif current_state == ApartmentState.MTA:
print('Current state: MTA')
# start dialogs via CLR
thread = Thread(ThreadStart(dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
# start dialogs via Tkinter
thread = Thread(ThreadStart(tk_dialog_thread))
thread.SetApartmentState(ApartmentState.STA)
thread.Start()
thread.Join()
2) Force STA mode via CoInitialize/CoInitializeEx before CLR does so for MTA:
# importing ctypes stuff
import ctypes
co_initialize = ctypes.windll.ole32.CoInitialize
# importing tkinter stuff
import tkinter as tk
from tkinter.filedialog import askdirectory, askopenfilename
# Force STA mode
co_initialize(None)
# importing pythonnet
import clr
# dialogs test
root = tk.Tk()
root.withdraw()
askdirectory()
askopenfilename()
I have tested the code which you pasted on Pycharm 2018.1.3 with python-3.6.5 installed on win-7 64 bit machine. It works fine without any error. There are few bugs in 2017 version. Try upgrading to latest version of Pycharm

(Python3.4) tkinter messagebox not work when it executed by cx_freeze

import sys
from cx_Freeze import setup, Executable
build_exe_options = {'packages': ['os','tkinter','random',
'heapq','collections','sys','pickle']}
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup( name = 'Game',
version = '0.02',
description = 'My GUI application!',
options = {'build_exe': build_exe_options},
executables = [Executable('Game.py', base=base)])
here's the code of the setup
from tkinter import *
value_a = 'hahaha'
a =messagebox.showinfo('laugh',value_a)
and the code that would executed
the erorr is Nameerorr : name "messagebox" is not defined when I typed python 123.py build or python haha.py build in cmd
I already used import *, if I run the code it shows message but neither in cmd nor .exe
Should I use import tkinter as tk? But it is difficult to read my code by adding "tk", I want to keep import * so that no "tk.xxx" is needed and it will still works on exe.
from tkinter import * does not work for messagebox, so you must import the message box individually like below
from tkinter import messagebox
I had this problem too. It worked OK in the IDE but not in direct run mode.
Adding import tkinter.messagebox as messagebox fixed the problem.
Thanks, G.

Python / cx_Freeze: askopenfile / askdirectory /// filedialog

I've got a problem.
I've got a program // script, which works perfectly, but when I compile it using cx_Freeze, it doesn't work: Name "filedialog" is not defined.
Do I have to import it on another way??
My Script part:
from tkinter import *
from shutil import *
import sys
import os
#Vars:
location = os.path.dirname(sys.argv[0])+"/"
if os.path.isfile(location+"filedic.txt"):
file = open(location+"filedic.txt","r").read()
else:
fiRoot = Tk()
fiRoot.withdraw()
file = str(filedialog.askdirectory())
And my setup script:
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(
name = "BlackChat",
version = "1.3",
description = "BlackChat was programmed by David Jandrey",
executables = [Executable("BlackChat.py", base = base,icon = "BlackChat.ico")])
Thanks for coming answers.
Reposting as an answer:
Doing from tkinter import filedialog explicitly might make it work - it looks like cx_Freeze isn't copying the filedialog module.

Categories