I'm trying to import the User class from a file called gui.py into another called snake.py. I want to import the class so that I can use ,a method within the class and an instance of the class called current_user. But when I do:
from gui import User
It imports everything from gui.py. Does anyone know where I've gone wrong and what I can do to fix this?
I'm new to working with multiple files in Python and this is quite confusing to me.
The files for this are available at:
https://github.com/VladRadoi08/Snake-LoginUI
Thanks!
Anything in the file you import will be run. To prevent this, try putting all the code you don't want to run within this conditional:
if __name__ == "__main__":
That will ensure it only runs if you actually run the python file instead of importing it.
I am attempting to use a module named "global_data" to save global state information without success. The code is getting large already, so I`ll try to post only the bare essentials.
from view import cube_control
from ioserver.ioserver import IOServer
from manager import config_manager, global_data
if __name__ == "__main__":
#sets up initial data
config_manager.init_manager()
#modifies data
io = IOServer()
#verify global data modified from IOServer.__init__
global_data.test() #success
#start pyqt GUI
cube_control.start_view()
So far so good. However in the last line cube_control.start_view() it enters this code:
#inside cube_control.py
def start_view():
#verify global data modified from IOServer.__init__
global_data.test() #fail ?!?!
app = QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())
Running the global_data.test() in this case fails. printing the entire global state reveals it now somehow reverted back to the data setup by config_manager.init_manager()
How is this possible?
While Qt is running I have a scheduler called every 10 seconds, also reporting a failed test.
However once the Qt GUI is stopped (clicked "x"), and I run the test from console, it succeeds again.
Inside the global_data module I`ve attempted to store the data in a dict inside both a simple python object as well as a ZODB in memory database:
#inside global_data
state = {
"units" : {}
}
db = ZODB.DB(None) #creates an in memory db
def test(identity="no-id"):
con = db.open()
r = con.root()
print("test online: ", r["units"]["local-test"]["online"], identity)
con.close()
Both have the exact same problem. Above the test is only done using the db.
The reason I attempted to use a db is that I understand threads can create a completely new global dictionary. However the 2 first tests are in the same thread. The cyclic one is in its own thread and could potentially create such a problem...?
File organization
If it helps my program is organized with the following structure:
There is also a "view" folder with some qt5 GUI files.
The IOServer attempts to connect to a bunch of OPC-UA servers using the opcua module. No threads are manually started there, although I suppose the opcua module does to stay connected.
global_data id()
I attempted to also print(id(global_data)) together with the tests and found that the ID is the same in IOServer AND top level code, but changes inside the cube_control.py#start_view. Should not these always refer to the same module?
I`m still not sure what exactly happened. But apparently this was solved by removing the init.py file inside of the folder named manager. Now all imports of the module named "global_data" points to the same ID.
How using a init.py file caused a second instance of the same module remains a mystery
I have a file, Foo.py which holds the code below. When I run the file from command line using, python Foo.py everything works. However, if I use CLI of python
python
import Foo
Foo.main()
Foo.main()
Foo.main()
The first call works fine, the second brings forward all hell of warnings, the first of which is
(python:5389): Gtk-CRITICAL **: IA__gtk_container_add: assertion 'GTK_IS_CONTAINER (container)' failed
And the last cause a segmentation fault. What's the problem with my code?
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import os
from PyQt4 import Qt
from PyQt4 import QtGui,QtCore
class Foo (QtGui.QWidget):
def __init__(self,parent=None):
super(Foo,self).__init__()
self.setUI()
self.showMaximized()
def setUI(self):
self.setGeometry(100,100,1150,650)
self.grid = QtGui.QGridLayout()
self.setLayout(self.grid)
#For convininece, I set different ui "concepts" in their own function
self.setInterfaceLine()
self.setMainText()
def setMainText(self):
#the main box, where information is displayed
self.main_label = QtGui.QLabel('Details')
self.main_text = QtGui.QLabel()
self.main_text.setAlignment(QtCore.Qt.AlignTop)
#Reading the welcome message from file
self.main_text.setText('')
self.main_text.setWordWrap(True) #To handle long sentenses
self.grid.addWidget(self.main_text,1,1,25,8)
def setInterfaceLine(self):
#Create the interface section
self.msg_label = QtGui.QLabel('Now Reading:',self)
self.msg_line = QtGui.QLabel('commands',self) #the user message label
self.input_line = QtGui.QLineEdit('',self) #The command line
self.input_line.returnPressed.connect(self.executeCommand)
self.grid.addWidget(self.input_line,26,1,1,10)
self.grid.addWidget(self.msg_label,25,1,1,1)
self.grid.addWidget(self.msg_line,25,2,1,7)
def executeCommand(self):
fullcommand = self.input_line.text() #Get the command
args = fullcommand.split(' ')
if fullcommand =='exit':
self.exit()
def exit(self):
#Exit the program, for now, no confirmation
QtGui.QApplication.quit()
def main():
app = QtGui.QApplication(sys.argv)
foo = Foo(sys.argv)
app.exit(app.exec_())
if __name__ in ['__main__']:
main()
I'm able to reproduce in Python 3 but not Python 2.
It's something about garbage collection and multiple QApplications. Qt doesn't expect multiple QApplications to be used in the same process, and regardless of whether it looks like you're creating a new one every time, the old one is living on somewhere in the interpreter. On the first run of your main() method, You need to create a QApplication and prevent it from being garbage collected by storing it somewhere like a module global or an attribute to a class or instance in the global scope that won't be garbage collected when main() returns.
Then, on subsequent runs, you should access the existing QApplication instead of making a new one. If you have multiple modules that might need a QApplication but you don't want them to have to coordinate, you can access an existing instance with QApplication.instance(), and then only instantiate one if none exists.
So, changing your main() method to the following works:
def main():
global app
app = QtGui.QApplication.instance()
if app is None:
app = QtGui.QApplication(sys.argv)
foo = Foo(sys.argv)
app.exit(app.exec_())
It's odd you have to keep a reference to ensure the QApplication is not garbage collected. Since there is only supposed to be one per process, I would have expected it to live forever even if you don't hold onto a reference to it. That's what seems to happen in Python 2. So ideally the global app line would not be needed above, but it's there to prevent this garbage collection business.
We're kind of stuck in the middle about how immortal this QApplication object is ... it's too long lived for you to be able to use a new one each time, but not long-lived enough on its own for you to re-use it each run without having to prevent its garbage collection by holding onto a reference. This might be bug in PyQt, which probably ought to do the reference holding for us.
There must be only on QApplication instance in one process. GUI frameworks are not prepared for multi-application mode.
I can't actually reproduce the problem, which at least shows there's nothing fundamentally wrong with the code.
The problem is probably caused by some garbage-collection issues when the main function returns (the order of deletion can be unpredictable).
Try putting del foo after the event-loop exits.
I'm new to Python and ran into a problem where methods in the class Gui always get executed twice.
Here is the gui class which inherits from Tkinter:
from Tkinter import *
class Gui (Tk):
def createKdWindow(self):
print("createKdWindow has been triggered")
def activate(self):
print ("activate has been triggered")
self.tk.mainloop()
and here is where the methods get called from (init.py):
from pm_test.gui import Gui
datgui = Gui()
datgui.createKdWindow()
datgui.activate()
When I run my program, I get the following console output:
createKdWindow has been triggered
activate has been triggered
createKdWindow has been triggered
activate has been triggered
So my methods were executed twice. I don't know where this is coming from. Does anybody know how to solve this?
Fixed:
Putting the code from init.py into a new module fixed this issue!
Fixed: Putting the code from init.py into a new module fixed this issue!
I'm working on a pygame project and have the main engine layed out. The problem is I hit a bug that I just can not seem to figure out. What happens is one module can't read a variable from another module.
It's not that the variable can't be read, it just sees an empty list instead of what it really is.
Instead of posting the entire source code I reproduced the bug in two small snippets that hopefully a skillful python-ist can interpret in his\her head.
Code:
main.py (This is the file that gets run)
import screen
screens = [] #A stack for all the game screens
def current_screen():
#return a reference to the current screen
return screens[-1]
def play():
print'play called'
current_screen().update()
if __name__=='__main__':
screens.append(screen.Screen())
play()
screen.py
import main
class Screen:
def __init__(self):
print'screen made'
def update(self):
print main.screens
#Should have a reference to itself in there
Thanks!
Don't import the main script. When you run the main.py file directly, it becomes the __main__ module. When you then import main, it will find the same file (main.py) but load it a second time, under a different module object (main instead of __main__.)
The solution is to not do this. Don't put things you want to 'export' to other modules in the main script. It won't work right. Put them in a third module. Or, pass them as arguments to the functions and classes you're calling.
The whole point of if __name__=='__main__': is to prevent code from being run when a module is imported. So when you import main from screen, that part isn't run and the list stays empt and play() is never called either.