Tkinter freezing Python and Windows Explorer - python

I often used Tkinter to prompt users and get the path to a file. However, I am facing a recurrent issue, when the filedialog appears it often crashes Windows.
The screen freezes, everything is blocked and when I enter the Task Manager I can see "Python is not responding", when I try to kill Python, then the Task Manager itself freezes and my only option then is to reboot my laptop.
Here is a sample code of what I usually do :
import tkinter as tk
from tkinter import filedialog
import os
window=tk.Tk()
currdir=os.getcwd()
path=filedialog.askopenfilename(parent=window, initialdir=currdir, title="Select file")
Am I doing something wrong ? Any tips ? Is it just bad performances from this library ?

Have you tried using a try/ except block so that you'll exit the loop even if you hit an exception?
import tkinter as tk
from tkinter import filedialog
import os
try:
window=tk.Tk()
currdir=os.getcwd()
path=filedialog.askopenfilename(parent=window, initialdir=currdir, title="Select file")
finally:
window.mainloop()

Include
window.mainloop()
At the end of your GUI file and see if it works that way

Thanks #User9701 and #Linden
Following your advice, I updated my code as per the below :
import tkinter as tk
from tkinter import filedialog
import os
try:
window=tk.Tk()
currdir=sos.getcwd()
path=filedalog.asopenfilename(parent=window,initialdir=currdir, title="Select file")
finally:
window.destroy()

Related

tkFileDialog and pyperclip prevent script from exiting

A script with both tkFileDialog and pyperclip imported won't exit. (Python2.7)
Working examples, where my script exits as expected:
import Tkinter, tkFileDialog
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
root.destroy()
As well as:
import pyperclip
print ('whatever')
Yet the following will prevent my script from exiting (raise SystemExit added for emphasis):
import Tkinter, tkFileDialog
import pyperclip
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
root.destroy()
raise SystemExit
Just importing both modules works fine, a tkFileDialog must be opened in order to create the error.
Calling os._exit() or any code that raises SystemExit soft-locks the interpreter or the python-process, when called as a script.
It seems, that the problem occurs when pyperclip is loaded when opening a tkFileDialog, since the following fragment works as expected:
import Tkinter, tkFileDialog
root = Tkinter.Tk()
root.withdraw()
file_path = tkFileDialog.askopenfilename()
root.destroy()
import pyperclip
raise SystemExit
In any case, though, every line of code after the critical part is executed as expected, raising SystemExit will create a soft-lock though.
This can't be used as a workaround though since python doesn't allow unloading of modules.
What am I doing wrong? Any ideas for a workaround?
Not a real solution, but the best I could come up with:
Switching from python 2.7 to python 3.7 (and therefore from Tkinter 8.5 to 8.6) does the trick for me.
Of course, this has a lot of other implications, that I couldn't test.
On a sidenote - since others couldn't replicate the issue:
I got the chance to run my code-snippet on yet another Windows 10-machine - it worked flawlessly with the same setup. So the problem definitely has something to do with the underlying system, not pyperclip or Tkinter itself.

ubuntu filedialog.askdirectory too low version

I was trying to call the file dialog of ubuntu to choose a directory with python3.6, and the code looks like this:
from tkinter import filedialog
filedialog.askdirectory()
but when i run this, a very old version file dialog shows:
Any idea on how to call the newest file dialog of ubuntu using python?
It is not old version, it is standard theme for GTK. You would have to use theme to change it. But Linux has only three styles as default
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
root = tk.Tk()
root.style = ttk.Style()
print(root.style.theme_names())
root.style.theme_use('clam')
filedialog.askdirectory()
root.mainloop()
classis/default:
clam:
alt:
You can get more themes installing module
pip install ttkthemes
And code
import tkinter as tk
from tkinter import ttk
import ttkthemes
root = tk.Tk()
root.style = ttkthemes.ThemedStyle()
for i, name in enumerate(sorted(root.style.theme_names())):
b = ttk.Button(root, text=name, command=lambda name=name:root.style.theme_use(name))
b.pack(fill='x')
root.mainloop()
List of styles
kroc:
radiance:
The UI components provided by tkinter (and the underlying tk library) are different from the UI components provided by, say, the GTK or the Qt libraries that are probably used by your desktop.
tkinter has a set of alternative widgets, that you can access with
from tkinter.ttk import *
that support the look and feel of your desktop, but (afaict) unfortunately the
filedialog widget is not supported.

Pycharm automatically closes a program, python idle doesnt

When running a tkinter program in the standard python idle program the window displays and you are able to interact with it, yet running the same program in pycharm causes the program window to flash up briefly then close.
I'm assuming its to do with the mainloop, what do you need to modify in your code to prevent the program from automatically closing when running in pycharm
An excert from my code follows
from tkinter import *
import tkinter
from tkinter import Text, Tk, ttk
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, root):
....
def main():
global label
root = Tk()
root.title(" My program")
root.geometry("550x330+600+300")
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
root.configure(bg=mycolor)
gui = GUI(root)
main()
Update : After a bit of mucking around, partly due to my code not being the best (rookie), I've managed to get it to work. For anyone interested heres the modification:
from tkinter import *
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, master):
self.master = master
master.title(" My Programs")
master.geometry("550x330+600+300")
master.iconbitmap('logo.ico')
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
master.configure(bg=mycolor)
....... Most of the above is program set up stuff but shown
MAIN CODE HERE
root = Tk()
gui = GUI(root)
root.mainloop()
Works now as expected
Python has a -i startup option which cause Python to enter interactive move when the program finishes, instead of exiting. IDLE executes code as if one entered python -i file.py at the terminal. This allows one to interactively explore the live gui by entering code in the Shell.
From this question and the one referenced by flyingmeatball, it appears that PyCharm does not use or simulate -i. So one must finish a tkinter program with root.mainloop to see anything. Unless one adds a button to quit the mainloop without destroying the application, one will not be able to interact with interactive statements. (Again, this is completely based on what has been posted on SO, as I have no experience with PyCharm.)

Tkinter program consumes all RAM/CPU

I ran this code and the RAM in my computer with my processor looks like it's going to explode! What is the reason?
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
import os
bloque1=Tk()
bloque1.title('Bloque1')
bloque1.config(bg="#1C1C1C")
bloque1.geometry("450x410")
barramenu=Menu(bloque1)
menubar=Menu(bloque1)
menubar.add_cascade(label="Actividades", menu=menubar)
menubar.add_command(label="Instrucciones")
menubar.add_command(label="Ayuda")
menubar.add_command(label="Cerrar", command=bloque1.quit)
bloque1.config(menu=menubar)
bloque1.mainloop()
You are adding a menu to itself. No doubt this is causing an infinite loop inside of Tkinter.
menubar.add_cascade(label="Actividades", menu=menubar)
That menu= attribute needs to be given another menu that will appear when you select that cascade entry from the menubar.

Python tkinter 8.5 import messagebox

The following code runs fine within IDLE, but otherwise I get "NameError: global name 'messagebox' is not defined". However, if I explicitly state from tkinter import messagebox, it runs fine from where ever.
from tkinter import *
from tkinter import ttk
root = Tk()
mainFrame = ttk.Frame(root)
messagebox.showinfo("My title", "My message", icon="warning", parent=mainFrame)
Why does IDLE not need the explicit import statement but elsewhere it is required?
the messagebox is a separate submodule of tkinter, so simply doing a complete import from tkinter:
from tkinter import *
doesn't import messagebox
it has to be explicitly imported like so:
from tkinter import messagebox
in the same way that ttk has to be imported explicitly
the reason it works in idle is because idle imports messagebox for its own purposes, and because of the way idle works, its imports are accessible while working in idle
IDLE is written in Python and uses Tkinter for the GUI, so it looks like your program is using the import statements that IDLE itself is using. However, you should explicitly include the import statement for the messagebox if you want to execute your program outside the IDLE process.
messagebox.showinfo is defined inside tkinter/showinfo.py but when you use from tkinter import * you only import tkinter/__init__.py which holds the definitions of Label, Entry, Button, ... That is how python imports work.
When you use from tkinter import messagebox it looks for messagebox inside tkinter/__init__.py but it can't find it so it tries to import tkinter/messagebox.py
As for the IDLE anomaly, it is a bug in IDLE and I believe that it was patched.

Categories