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

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.

Related

NameError: name 'win' is not defined with tkinter 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?

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)

python import circular dependency (and perhaps function declaration)

Hello I did got into circular dependency what is not refactori-zable other than doubling code.
I have something like this (only much more complex):
myParser.py:
import sys
import main #comment this to make it runnable
def parseEvnt():
sys.stdout.write("evnt:")
main.parseCmd(1) #comment this to make it runnable
tbl.py:
import myParser
tblx = {
1:("cmd",),
2:("evnt",myParser.parseEvnt),
}
main.py:
import tbl
def parseCmd(d):
print(tbl.tblx[d][0])
data=[1,2]
for d in data:
if(d<2):
parseCmd(d)
else:
fce = tbl.tblx[d][1]
fce()
Obvious error I'm getting is:
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 1, in <module>
import tbl
File "D:\Data\vbe\workspace\marsPython\testCircular2\tbl.py", line 1, in <module>
import myParser
File "D:\Data\vbe\workspace\marsPython\testCircular2\myParser.py", line 2, in <module>
import main
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 7, in <module>
parseCmd(d)
File "D:\Data\vbe\workspace\marsPython\testCircular2\main.py", line 3, in parseCmd
print(tbl.tblx[d][0])
AttributeError: module 'tbl' has no attribute 'tblx'
In C I think I would just tell by declaration in tbl.py hey there is function parseEvnt(). I would not need to include myParser and there would be no circular include.
In python I do not know how to do it.
I read few threads and there is always some wise guy recommending refactorizing. But in this case parseCmd() needs to see tblx which needs to see parseEvnt() (unless function declaration) and parseEvnt() need to call parseCmd() (cos evnt contains triggering cmd and I do not want to double the decoding cmd code).
Is there way how to make it working in python?
You can frequently get away with circular dependencies as long as the modules don't try to use each other's data until all importing is complete - as a practical matter, that means referencing with namespace (from module import something is forbidden) and only using the other modules inside functions and methods (no mystuff = module.mystuff in the global space). That's because when importing starts, python puts the module name in sys.modules and won't try to import that module again.
You ran into trouble because when you run main.py, python adds __main__ to sys.modules. When the code finally came around to import main, there was no "main" in the module list and so main.py was imported again... and its top level code tried to run.
Lets rearrange your test case and throw in a few print statements to tell when import happens.
myParser.py
print(' + importing myParser')
import sys
print('import parsecmd')
import parsecmd
def parseEvnt():
sys.stdout.write("evnt:")
parsecmd.parseCmd(1)
tbl.py
print(' + importing tbl')
print('import myParser')
import myParser
tblx = {
1:("cmd",),
2:("evnt",myParser.parseEvnt),
}
Parsecmd.py (new)
print(' + importing parsecmd')
print('import tbl')
import tbl
def parseCmd(d):
print(tbl.tblx[d][0])
main.py
print('running main.py')
print('import parsecmd')
import parsecmd
if __name__ == "__main__":
data=[1,2]
for d in data:
if(d<2):
parsecmd.parseCmd(d)
else:
fce = parsecmd.tbl.tblx[d][1]
fce()
When I run it I get
running main.py
import parsecmd
+ importing parsecmd
import tbl
+ importing tbl
import myParser
+ importing myParser
import parsecmd <-- didn't reimport parsecmd
cmd
evnt:cmd
If you're insistent on not refactoring (which is the real solution to this - not being a wise guy), you could move your problematic import into your function in myParser.py
import sys
def parseEvnt():
import main ## import moved into function
sys.stdout.write("evnt:")
main.parseCmd(1)
Again, see if you can redesign your code so such interdependencies are avoided.
The above solution is sort of a hack and won't solve future problems you might run into due to this dependency.
Circular imports should be avoided. Refactoring is required, any workaround that still requires a circular import is not a good solution.
That being said, the refactoring doesn't have to be extensive. There are at least a couple of fairly simple solutions.
Solution 1: move shared functions to a shared module
Since you want to use parseCmd from more than one place, move it to a separate file. That way both main.py and myParser.py can import the function.
Solution 2: have main pass parseCmd to parseEvnt.
First, make parseEvnt accept an argument to tell it which function to run:
# myParser.py
import sys
def parseEvnt(parseCmd):
sys.stdout.write("evnt:")
parseCmd(1)
Next, when you call myParser.parseEvnt, pass in a reference to main.parseCmd:
# main.py:
...
else:
fce = tbl.tblx[d][1]
fce(parseCmd)
There are other ways to accomplish the same thing. For example, you could add a "configure" method in myParser, and then have main.py call the configure method and pass in a reference to its parseCmd. The configure method can then store this reference in a global variable.
Another choice is to import main in the function that uses it:
main.py
import sys
def parseEvnt():
import main
sys.stdout.write("evnt:")
main.parseCmd(1)

Using python static class C#/Java style, scope difference errors

I have two files, namely game.py and map.py. The following simplified code resides in them:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from datetime import *
from map import *
class Game:
Scene = QGraphicsScene
View = QGraphicsView
#staticmethod
def start():
Game.App = QApplication(sys.argv)
Game.Scene=QGraphicsScene();
Game.Scene.setBackgroundBrush(QBrush(QColor(Qt.green)));
Game.View=QGraphicsView(Game.Scene);
print Game
map=Map()
Game.App.exec_()
if __name__=='__main__':
Game.start()
and file map.py:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from game import *
class Map(QObject):
def __init__(self,parent=None):
super(Map,self).__init__(parent);
print Game
v=Game.View
print v
v.setWindowTitle("sth")
Running game.py results in
__main__.Game
game.Game
<class 'PyQt4.QtGui.QGraphicsView'>
Traceback (most recent call last):
File "/home/abiusx/workspace/borj/trunk/game.py", line 119, in <module>
Game.start()
File "/home/abiusx/workspace/borj/trunk/game.py", line 66, in start
map=Map()
File "/home/abiusx/workspace/borj/trunk/map.py", line 16, in __init__
v.setWindowTitle("asb")
TypeError: QWidget.setWindowTitle(QString): first argument of unbound method must have type 'QWidget'
The problem is, the code in map.py that references Game.View, detects it as a class (as defined in class body) but not what is overwritted on it (an actual instance).
Also Game is known as main.Game in game.py but as game.Game in map.py
Could anyone help me?
the code in map.py that references Game.View, detects it as a class
That's because View = QGraphicsView sets it to a class. It only becomes an instance when you run Game.start. (To be honest, I don't understand why you're setting this class variable to a class object initially, or why the Game class exists at all.)
Also Game is known as main.Game in game.py but as game.Game in map.py
The module name changes to __main__ when you run a module as a script.
Whenever a file is read in Python, when it reaches a class definition it defines that class.
In my scenario, game and map both relied on each other. this is a well known circular reference problem in python.
I added another module, main.py, used game and map in it, and game in map. Problem solved.

Can someone explain this unexpected Python import behavior?

I've run into some behavior from Python 2.6.1 that I didn't expect. Here is some trivial code to reproduce the problem:
---- ControlPointValue.py ------
class ControlPointValue:
def __init__(self):
pass
---- ControlPointValueSet.py ----
import ControlPointValue
---- main.py --------------------
from ControlPointValue import *
from ControlPointValueSet import *
val = ControlPointValue()
.... here is the error I get when I run main.py (under OS/X Snow Leopard, if it matters):
jeremy-friesners-mac-pro-3:~ jaf$ python main.py
Traceback (most recent call last):
File "main.py", line 4, in <module>
val = ControlPointValue()
TypeError: 'module' object is not callable
Can someone explain what is going on here? Is Python getting confused because the class name is the same as the file name? If so, what is the best way to fix the problem? (I'd prefer to have my python files named after the classes that are defined in them)
Thanks,
Jeremy
I don't think it's unexpected. What you are basically doing is:
1) the first import in main.py imports the contents of ControlPointValue module into the global namespace. this produces a class bound to that name.
2) the second import in main.py imports the contents of ControlPointValueSet module into the global namespace. This module imports ControlPointValue module. This overwrites the binding in the global namespace, replacing the binding for that name from the class to the module.
To solve, I would suggest you not to import *, ever. Always keep the last module prefix. For example, if you have foo/bar/baz/bruf.py containing a class Frobniz, do
from foo.bar.baz import bruf
and then use bruf.Frobniz()
In addition to the other suggestions about star imports, don't name your module and your class the same. Follow pep8's suggestions and give your modules short all lower case names and name your classes LikeThis. E.g.
---- controlpoints.py ------
class ControlPointValue:
def __init__(self):
pass
---- valuesets.py ----
from controlpoints import ControlPointValue
---- main.py --------------------
from controlpoints import ControlPointValue
from valuesets import *
val = ControlPointValue()

Categories