NameError: name 'win' is not defined with tkinter python - python

After Executing This code i am getting error win not found running tkinter from different function is important as its a homework
Code:
import tkinter as tk
from tkinter import *
def zui(kaj,saj):
zun=kaj
kaj=kaj+"=tk.Tk()"
exec(kaj)
saj=zun+".title('"+saj+"')"
exec(saj)
def zabel(self,naj,iaj,oaj,baj,gaj,taj):
spsp=self+"="+"Label("+naj+", text='"+iaj+"', bg='"+oaj+"', height="+gaj+", width="+taj+",fg='"+baj+"')"
spsp=str(spsp)
exec(spsp)
def zosition(qak,iak,nak):
sspp=qak+".grid(row="+iak+", column="+nak+")"
exec(sspp)
def zainzoop(tak):
sft=tak+".mainloop()"
exec(sft)
zui("win","zahid app")
zabel("label","win","hello world","white","black","4","10")
zosition("win","1","1")
zainzoop("win")
Traceback:
Traceback (most recent call last):
File "c:/PyProjects/Patient Data Entry/hello.py", line 20, in <module>
zabel("label","win","hello world","white","black","4","10")
File "c:/PyProjects/Patient Data Entry/hello.py", line 12, in zabel
exec(spsp)
File "<string>", line 1, in <module>
NameError: name 'win' is not defined

This is a very weird way on using tkinter, anyway who am I to judge. exec() takes a globals() argument to make the declaration global. This is how the exec should look like:
exec(spsp,globals())
exec(sspp,globals())
exec(sft,globals())
and then in the end, zosition() should be called like:
zosition("label","1","1")
Just in case your curious on how it would normally look like:
import tkinter as tk
kaj = tk.Tk()
kaj.title('zahid app')
spsp = tk.Label(kaj,text='Hello World',bg='white',fg='black',height=4,width=10)
spsp.grid(row=1,column=1)
kaj.mainloop() #much easier right?

Related

Why does from tkinter import * not import Tkinter's messagebox?

I am learning Python, and as I try some code using tkinter I hit this issue:
I import all the definitions of tkinter with the line:
from tkinter import *
Then I try to open a message box:
messagebox.showinfo(message='My message')
But when I run the program, if this line must be executed, I get the message:
Traceback (most recent call last):
File ...
...
NameError: name 'messagebox' is not defined
If I add to the import line an explicit import for messagebox:
from tkinter import *
from tkinter import messagebox
it works, but I don't understand the reason why I have to add this import.
messagebox is a module, e.g. messagebox.py. This is not automatically imported into the namespace when you from tkinter import *. What is automatically imported is what tkinter.__init__ defines as __all__:
__all__ = [name for name, obj in globals().items()
if not name.startswith('_') and not isinstance(obj, types.ModuleType)
and name not in {'wantobjects'}]
Notice that tkinter even explicitly excludes anything that is types.ModuleType, which messagebox falls under.
When in doubt about this type of thing, you can always check out the CPython tkinter Python lib itself.
The Python docs' Importing * From a Package contain more detail.

Why do I receive an AttributeError even though import, spelling and file location is correct?

I am using PyCharm
All files are in the directory 'venv'
venv
NoteFunction.py
NoteMainApp.py
...
I split up my code in five separate files. One 'main' file, gathering all other files and creating eventually the GUI. The prefix for the files is 'Note' followed an appropriate description.
My problem now is the import of 'NoteTopMenu' into the main file 'NoteMainApp'.
The code is:
import NoteStatusbar as SB
import NoteTopMenu as TM
import NoteWidgets as NW
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self,parent)
super().__init__(parent)
self.topbar = TM.TopMenu(parent)
self.widget = NW.FrontFrames(parent)
self.statusbar = SB.StatusBar(parent)
root = tk.Tk()
MainApp(root).pack(side="top", fill="both")
root.mainloop()
I receive the error message:
Traceback (most recent call last):
File "C:/Users/PycharmProjects/MindNotez/NoteMainApp.py", line 2, in <module>
import NoteTopMenu as TM
File "C:\Users\PycharmProjects\MindNotez\NoteTopMenu.py", line 2, in <module>
import NoteMainApp as Main
File "C:\Users\PycharmProjects\MindNotez\NoteMainApp.py", line 29, in <module>
MainApp(root).pack(side="top", fill="both")
File "C:\Users\PycharmProjects\MindNotez\NoteMainApp.py", line 13, in __init__
self.topbar = TM.TopMenu(parent)
AttributeError: module 'NoteTopMenu' has no attribute 'TopMenu'
The code in NoteTopMenu is:
import NoteMainApp as Main
import NoteWidgets as NW
import tkinter as tk
class TopMenu(NW.FrontFrames):
"""Class creating the top menu bar."""
def __init__(self, master):
super().__init__(master)
# *******Top-Navigation Bar (tnb)**********
tnb = tk.Menu(master)
Main.root.config(menu=tnb)
....
If I comment the NoteTopMenu out in the main file, the code runs without a problem. I checked my spelling but PyCharm also offers me code-completion. Therefore, PyCharm finds the file, the module, my class and other module are imported without an issue. Do you know why the file/module is not being found or fails to be imported?
Full code is here on GitHub: MindNotez
Thank you very much for your help!
You invoke NoteMainApp.py which imports NoteTopMenu.py which imports NoteMainApp.py which does not go on to re-import NoteTopMenu.py (because the import has already started). The import of NoteMainApp.py then goes on to parse the rest of the file. At this point the module NoteTopMenu is defined, but it doesn't have any attributes (because you haven't got round to defining them yet) ... hence the error.
I suggest that NoteTopMenu.py should not import NoteMainApp.py (and if there are any bits which both files need, they should be moved into another file that both can import)

root.after unable to find function_name

I am trying to put together a GUI that would read from a continuously updated TXT file and updated every once in a while. So far I succeeded with the first part and I am failing to use 'root.after()' to loop the whole thing but it results in NameError:
import tkinter as tk
root = tk.Tk()
class App:
def __init__(self, root):
frame = tk.Frame(root)
frame.pack()
iAutoInEN = 0
iAvailableEN = 0
self.tkAutoInEN = tk.StringVar()
self.tkAutoInEN.set(iAutoInEN)
self.tbAutoInEN = tk.Label(root, textvariable=self.tkAutoInEN)
self.tbAutoInEN.pack(side=tk.LEFT)
self.button = tk.Button(frame, text="Start", fg="red",
command=self.get_text)
self.button.pack(side=tk.LEFT)
def get_text(self):
fText = open("report.txt") #open a text file in the same folder
sContents = fText.read() #read the contents
fText.close()
# omitted working code that parses the text to lines and lines
# to items and marks them with numbers based on which they are
# allocated to a variable
if iLineCounter == 1 and iItemCounter == 3:
iAutoInEN = int(sItem)
self.tkAutoInEN.set(iAutoInEN)
root.after(1000,root,get_text(self))
app = App(root)
root.mainloop()
try:
root.destroy() # optional; see description below
except:
pass
The first instance runs without any problems and updates the value from 0 to the number in the TXT file but is accompanied with an error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\...\Python35\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/.../pythonlab/GUI3.py", line 117, in get_text
self.after(1000,root,get_text())
NameError: name 'get_text' is not defined
EDIT:
When changed to the recommended "self.after(1000,self.get_text)"
class App:
...
def get_text(self):
fText = open("report.txt") #open a text file in the same folder
sContents = fText.read() #read the contents
fText.close()
# omitted code
if iLineCounter == 1 and iItemCounter == 3:
iAutoInEN = int(sItem)
self.tkAutoInEN.set(iAutoInEN)
self.after(1000,self.get_text)
Error changes
Traceback (most recent call last):
File "C:/.../pythonlab/GUI3.py", line 6, in <module>
class App:
File "C:/.../pythonlab/GUI3.py", line 117, in App
self.after(1000, self.get_text)
NameError: name 'self' is not defined
Also please consider this is my very first programme (not only) in Python, so I would appreciate if you are a little bit more explicit with your answers (e.g. when pointing out an indentation error, please refer to an exact line of code).
Because get_text is a method of App class you should call it as self.get_text.
After is a tkinter method. In that case you should call it as root.after. And self refers to the class you are in. So because get_text is a method of current class you should call is with self which is like this in other programming languages like Java.
...
root.after(1000, self.get_text)
...
Firstly, like James commented, you should fix your indentation so that the functions are a part of the class.
Then, change this line
root.after(1000,root,get_text(self))
to this
root.after(1000, self.get_text)
Check out the answer to the following question, which uses the code I just gave you:
Tkinter, executing functions over time

NameError: global name 'messagebox' is not defined - CONSOLE MODE

I've imported tkinter.messagebox, and my program runs smoothly when I F5 and test it on IDLE.
However my program doesn't run on console when a messagebox should be displayed, and I get the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\lib\tkinter\__init__.py", line 1456, in __call__
return self.func(*args)
File "U:\my documents\6th form\A2\Computing\F454\Code and Prototyping\trackeve
nts.py", line 204, in validation
messagebox.showerror("Data invalid", "The data you have entered is invalid.
Please make sure you have submitted it correctly.")
NameError: global name 'messagebox' is not defined
My importing of messagebox and the section of code if it's needed:
import tkinter.messagebox
def validation():
(...)
elif completedValidation == False:
messagebox.showerror("Data invalid", "The data you have entered is invalid. Please make sure you have submitted it correctly.")
If you import tkinter.messagebox, you have to refer to it as such: with tkinter.messagebox. If you want to alias it to just messagebox, you need from tkinter import messagebox.
try this
import Tkinter
import tkMessageBox
#rest of the code and replace the below line
tkMessageBox.showerror("Data invalid", "The data you have entered is invalid. Please make sure you have submitted it correctly.")

weird behaviour of late import and scopes

I have just discovered this strange scoping behaviour of both Python 2 and 3. When I'm adding a late import for a sub-module, the main import of toplevel module stops working. Viable example:
import os
def start():
import sys
print('in modules?', 'os' in sys.modules)
print('in globals?', 'os' in globals())
print('in locals?', 'os' in locals())
print('os =', os)
import os.path
os.path.exists('useless statement')
start()
The output will be:
in modules? True
in globals? True
in locals? False
Traceback (most recent call last):
File "test.py", line 15, in <module>
start()
File "test.py", line 9, in start
print('os =', os)
UnboundLocalError: local variable 'os' referenced before assignment
Any ideas?
This is nothing special about import statements. It's just how the scoping works in Python. If you're assigning a value to a label, it is local to the scope unless explicitly defined global.
Try this code -
a = 2
def start():
print a
a = 3
start()
This also fails with UnboundLocalError as your code because statement a = 3 makes the label a local to function start.

Categories