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.
Related
I am trying to re-use some code from the CoderBot project to build my own web controlled robot.
I am using python3 on a raspberry PI and I have simplified the code just to generate the error.
'''
class myclass():
objClass = None
def init(self):
print("initialised")
#classmethod
def get_it(cls):
if not cls.objClass:
print("objClass does not exist")
cls.objClass = myclass()
print("created")
return cls.objClass
def main(args):
method_list = [method for method in dir(myclass) if method.startswith('_') is False]
print(method_list)
makeone = myclass.get_it()
print(makeone)
print(myclass.get_it())
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
'''
when I run this the following output is produced
'''
['get_it', 'objClass']
objClass does not exist
initialised
created
<__main__.myclass object at 0x7fbe6e1fa0>
<__main__.myclass object at 0x7fbe6e1fa0>
'''
Everything is as I expected.
When I run this code in a separate script
'''
import ct
def main(args):
method_list = [attribute for attribute in dir(ct.myclass) if
callable(getattr(ct.myclass, attribute)) and attribute.startswith('__') is
False]
print(method_list)
two = ct.get_it()
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
'''
The following output is produced:
'''
['get_it']
Traceback (most recent call last):
File "/home/pi/classTest/mainct.py", line 35, in <module>
sys.exit(main(sys.argv))
File "/home/pi/classTest/mainct.py", line 30, in main
two = ct.get_it()
AttributeError: module 'ct' has no attribute 'get_it'
'''
This output is telling me that 'get_it' exists in the class, but not when I try and create one.
I am very confused and have looked at lots of tutorials but can't spot what I am doing wrong.
It is probably one of those errors where if I sat down and spoke to someone it would be obvious, but I can't spot it!
Steve
PS I hope the formatting is ok,
As jasonharper said, I was not referencing the class!
When I went back and looked at the original code I had not spotted the change in case.
so with my example the class MyClass should have been defined in a file myclass.py and then referenced as
from myclass import MyClass
then in the code
two = MyClass.get_it()
I have hopefully sorted out the formatting, the post was originally created on my PI and I spent 40 minutes trying to format it correctly.
This problem is definitely closed, thanks for replies
Is "ct" your class?
two = ct()
two.get_it()
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)
I am currently working on the framework for a simple turn based game. I am trying to call a definition within a class Inside of a separate file from my current one. The Program I am importing the moveset file from is called Pymon_Movesets. I am importing it into the Pymon_Main file. The code for both looks a little like this...
(Pymon_Moveset)
class normaltype():
def scratch():
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2
Pymon_Main
From Pymon_Movesets import *
def Initialize():
Scratch = Pymon_Movesets.normaltype.scratch()
Bite = Pymon_Movesets.normaltype.bite()
My Error
File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 2, in <module>
from Pymon_Movesets import * File "C:\Users\samsc\Desktop\Pymon\Pymon_Movesets.py", line 3, in <module>
import Pymon_main File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 110, in <module>
gamefunction.Initialize() File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 26, in Initialize
Scratch = Pymon_Movesets.normaltype.scratch() AttributeError: module 'Pymon_Movesets' has no attribute 'normaltype' The program
'[4908] python.exe' has exited with code -1073741510 (0xc000013a).
I am Using Visual Studios Python Editor.
Thank you for your time
You are importing all the contents of Pymon_Moveset.py into the current namespace, however, you still call the class using the filename. Also, you need to create an instance of the class before you call a method. Lastly, you need to include self in the method signature, so it is bound to the class:
In Pymon_Movesets:
class normaltype():
def scratch(self):
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2
In main file:
import Pymon_Movesets
def Initialize():
Scratch = Pymon_Movesets.normaltype().scratch()
Bite = Pymon_Movesets.normaltype().bite()
However, if you want to access the methods in the class using the name of the class and not an instance, use staticmethod:
In Pymon_Moveset.py:
class normaltype():
#staticmethod
def scratch():
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2
Since you're doing from Pymon_Movesets import *, no need to use Pymon_Movesets to call its normaltype function if it is a module-level / file-level function.
from Pymon_Movesets import *
def Initialize():
Scratch = normaltype.scratch()
Bite = normaltype.bite()
In all the tutorials on the web I've seen with Pyglet, it doesnt seems that any of them have used classes to contain the pyglet.window.Window instance. For example, most tutorials seem to go something like
import pyglet
game_window = pyglet.window.Window()
#game_window.event
def on_draw():
#dostuff
while __name__ == "__main__":
pyglet.app.run()
I'm having trouble restructuring this code into a class. My code which is intended to do so, is here:
import pyglet
from pyglet.gl import *
from Board import Board
class Frontend:
def __init__(self,xs, ys):
self.GameInstance = Board(xs,ys)
self.GameWindow = pyglet.window.Window(width=512, height=512,visible=False)
#GameWindow.event
def on_draw(self):
self.GameWindow.clear()
f = Frontend()
When I run this code, I get the following error:
Traceback (most recent call last):
File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 7, in <module>
class Frontend:
File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 13, in Frontend
#GameWindow.event
NameError: name 'GameWindow' is not defined
When I replace #GameWindow.event with #self.GameWindow.event in an attempt to resolve the NameError I get:
Traceback (most recent call last):
File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 7, in <module>
class Frontend:
File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 13, in Frontend
#self.GameWindow.event
NameError: name 'self' is not defined
Which i expect. However, I'm not sure why this code isnt working - can someone explain why and how to fix it?
You can inherit from Window.
This should work:
class Frontend(pyglet.window.Window):
def __init__(self, xs, ys):
self.GameInstance = Board(xs,ys)
super().__init__(width=512, height=512,visible=False)
def on_draw(self):
self.clear()
Your code is not working because you can not reference the instance of the Frontend class outside the methods. If you will have only one instance of the Frontend class you can do something like:
class Frontend:
window = pyglet.window.Window()
def __init__(self):
...
#window.event
def on_draw():
...
As I've commented on ragezor's answer, the pyglet docs recommend inheritance.
But another option may be to separate the event handling logic in its own class, as an EventDispatcher:
http://pyglet.org/doc-current/programming_guide/events.html#creating-your-own-event-dispatcher
Personally, if I knew would only have one Frontend instance, I would question the necessity of having a class. But that's a whole can of worms. Thought I'd give you another nice option, at least, you can't go wrong inheriting from Window though, especially if all your events are Window-related.
A third idea (fourth I guess since ragezor gave you two options):
class Frontend:
def __init__(self,xs, ys):
self.GameInstance = Board(xs,ys)
self.GameWindow = pyglet.window.Window(width=512, height=512,visible=False)
self.on_draw = self.GameWindow.event(self.on_draw)
def on_draw(self):
self.GameWindow.clear()
In other words, apply the #GameWindow.event decorator manually.
One last thing, don't use camelcase for attributes, it goes against PEP8 convention and confused me for a second while editing this code. Call it game_window instead.
My guess is that you need to do
#self.Gamewindow.event
I have a class, robot, in a file called robot.py
I want to create a robot instance in my main script like so:
in robot.py:
class robot(object):
def __init__(self,pygame,screen_width,screen_height):
in main.py:
import pygame, sys, copy
import mouse
import robot
import menu
import button
from pygame.locals import *
...
size = [1200,900]
my_robot = robot(pygame,size[0]-400,size[1]-100)
error:
me:cup-robot Me$ python run.py
Traceback (most recent call last):
File "run.py", line 24, in <module>
my_robot = robot(pygame,size[0]-400,size[1]-100)
TypeError: 'module' object is not callable
how do I do this?
Two choices :
import robot and then prefix all with robot :
my_robot = robot.robot(pygame,size[0]-400,size[1]-100)
or
from robot import robot and then your code should work. But then, you can see that you won't be able to distinguish if robot is a module or the class, so you should not name the class and the file with the same name.
Change your import statement:
from robot import robot
You have robot defined both as a module (robot.py) as well as a class. You need to import the class from the module so it is publicly available.