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!
Related
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 have a Python program where a function imports another script and runs it. But the script gets run only the first time the function is called.
def Open_Generator(event):
import PasswordGenerator
Any tips?
*The function is called using a button in a tkinter window
This is by design. You should only import a module once. Trying to import a module more than once will cause Python to re-fetch the module object from the cache, but this won't cause the module's code to execute a second time.
Most well-designed modules won't do anything right away when you import them, or at least won't do anything obviously visible. Generally, if you want a module to do work, you need to call one of its functions.
I'm guessing your PasswordGenerator module has some code at the file-level scope. In other words, it has code that isn't inside a function. Try to move that code into a function. Then you can call that function from Open_Generator.
import PasswordGenerator
def Open_Generator(event):
my_password = PasswordGenerator.generate_password()
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 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.
I'm sorry for the verbal description.
I have a wxPython app in a file called applicationwindow.py that resides in a package called garlicsimwx. When I launch the app by launching the aforementioned file, it all works well. However, I have created a file rundemo.py in a folder which contains the garlicsimwx package, which runs the app as well. When I use rundemo.py, the app launches, however, when the main wx.Frame imports a sub-package of garlicsimwx, namely simulations.life, for some reason a new instance of my application is created (i.e., a new identical window pops out.)
I have tried stepping through the commands one-by-one, and although the bug happens only after importing the sub-package, the import statement doesn't directly cause it. Only when control returns to PyApp.MainLoop the second window opens.
How do I stop this?
I think you have code in one of your modules that looks like this:
import wx
class MyFrame(wx.Frame):
def __init__(...):
...
frame = MyFrame(...)
The frame will be created when this module is first imported. To prevent that, use the common Python idiom:
import wx
class MyFrame(wx.Frame):
def __init__(...):
...
if __name__ == '__main__':
frame = MyFrame(...)
Did I guess correctly?
You could create a global boolean variable like g_window_was_drawn and check it in the function that does the work of creating a window. The value would be false at the start of the program and would change to True when first creating a window. The function that creates the window would check if the g_window_was_drawn is already true, and if it is, it would throw an exception. Then You will have a nice stacktrace telling You who is responsible of executing this function.
I hope that helps You find it. I'm sorry for the verbal solution ;)
Got it: There was no
if __name__=='__main__':
in my rundemo file. It was actually a multiprocessing issue: The new window was opened in a separate process.