Reputation: 1329
I'm new to tkinter and I want to read in a file. This simple operation turns out to be non-trivial. Here is my code:
import tkinter as tk
from matplotlib.backends.backend_tkagg \
import FigureCanvasTkAgg ### PROBLEM 1: REMOVING THIS IMPORT CAUSES AN
### ERROR WHEN OPENING THE DIALOG
def op():
global filename
filename = tk.filedialog.askopenfilename()
root = tk.Tk()
mainframe = tk.Frame(root)
mainframe.grid(column=0, row=0)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
tk.Button(mainframe, text="Open file", command=op).grid(column=0, row=1)
#print(filename) ### PROBLEM 2: UNCOMMENTING THIS CAUSES AN ERROR
### UNLESS I ADD <filename = ""> ABOVE THE op
### FUNCTION DEFINITION
root.mainloop()
Questions:
1) It seems very weird that importing a totally different package, matplotlib, actually has an influence over whether my program works or not. Without that import, clicking on the opening button causes an error. With it, it works fine.
Could this be a bug?
2) Why is filename
not accessible outside the function body, even though I'm declaring it global? A minimal working example that has the same structure as my tkinter code is this - and this works:
def test():
global testname
testname = 23
def call_test():
test()
call_test()
print(testname)
Oddly enough, I can get my tkinter code to not produce an error, if I insert a filename = ""
at the top - but I still can't actually print out the filename, it's just that the error disappears.
3) Is there any other, more elegant way to access the path of the file I'm opening without using global variables? What is the best practice?
Upvotes: 0
Views: 557
Reputation: 15355
I don't think it's fair to call matplotlib "...a totally different package...", let alone calling backend_tkagg
that. Internally the second import also imports filedialog
. That's why you don't need it. You can replace the second import simply with:
import tkinter.filedialog
At the time which:
print(filename)
is executed filename
simply does not exist as op
was never called before. Python isn't compiled, it is interpreted, it simply skips runtime error(s) until the lines that cause it are run. Try:
op()
print(filename)
to see the difference.
Your file path reader does work. It's just you try to print
the filepath
before it starts to exist, or before it has a path in it.
I think another way in the context would be:
...
def op():
global root
root.filename = tk.filedialog.askopenfilename()
print(root.filename)
Upvotes: 1