pyinstaller program keeps running in background after closing - python

I have a pyinstaller executable wxpython GUI that works fine. The only issue I am having is that when I close the program with the X button on the window, it stays running in the background. Does anyone know of a way to kill the process when the window X button is clicked?

You can bind the Close window event, which is wx.EVT_CLOSE like every other event i.e.:
self.Bind(wx.EVT_CLOSE, self.OnExit)
Then in you OnExit(self,event) use self.Destroy()
If that still doesn't work, you almost certainly have something still open. If you are unable to track that down, a workaround is using sys.exit() but that really should be frowned upon.

Related

How can I clear a run window while the program is running?

I have a code, and I want to be able to clear the run window after certain actions are performed, however I haven't been able to find a way to clear it aside from clearing it yourself using the 'clear all' button(PyCharm btw). Is it possible to do that?
It seems that you can't clear the pycharm terminal without the clear button, however running it in cmd, the os.system('cls') or os.system('clear') works and will clear the screen.
You can't clear the pycharm window without the clear all button, but the os.system('clear') will clear the window if you run it in cmd instead so use that instead..

Tkinter-based app keeps running in the background if the window is closed abruptly

I've created a tkinter app designed to let users create and take quizzes locally. Unfortunately, if a user closes the window by hitting the 'x' in the corner instead of hitting the "quit" button on the main menu, the window is destroyed but the process remains in the background. It isn't a huge deal as it stops using any CPU and only holds on to about 40mb of memory per instance, but this just seems pretty sloppy for an app that I'd like to deploy.
I have no idea what specifically is refusing to exit when the window is closed, and as it could be coming from almost anywhere in my 1700 lines of code, I'm instead looking for some more general tips for identifying what's still running or for killing any remaining processes when the window is closed. I'm happy to provide my code if anyone thinks it would help, though I reiterate that it's quite long given that I can't identify the source of the particular problem.
You can use state() from Tk to check if the window is open or not. When the window is open it should return 'normal' and if the window isn't open it will return something else.
What I would do is add something that checks the state of the window and exit the app when it's closed.
while app_is_running:
if root.state() != 'normal':
sys.exit(0)

wxPython not responding

I'm new to python and now I want to try wxpython, but I can't continue even at the very beginning.
Following the toturial,
import wx
app = wx.App(False)
frame = wx.Frame(None, wx.ID_ANY, "Hello World")
frame.Show(True)
after I did that, the new windows stops responding as soon as the it appears or I try to click it. Then I can only force close it and the editor restarts.
All the same on shell or IDLE, even all the same on different computers(I happened to bought a new one). Maybe I've done something wrong since I searched the internet and it seems no one encounters the problem, but I can't figure it out.
I'm using the latest python(x,y).
In addition, I tried tkinter also on my old computer and the problem is the same, if I remember rightly.
that's because the app loop is not running. usually, you also have to do:
app.MainLoop()
after frame.Show(). of course, now your console will be running the main loop, and you won't get your console back until after the app exits (well, when your main window closes), which probably isn't what you want either.
i haven't used python(x,y), but from a quick look, it looks like it supports IPython(x,y). If you use that as the console, then you can do
%gui wx
after loading, and then instead of creating/running the app yourself, IPython itself implements the app and does event processing in a special way as an input hook - which means that while it is waiting for you to type something, instead of just waiting, it actively polls the gui to see if there are active events and processes them if they are. This can create some interesting problems as well, but then you can just create the window & show it, and it will work correctly....

Closing threaded Tkinter window

I use a Tkinter window to visualize some output of my programm. The window is threaded (see basic structure below) and basically it works quite fine. So far, I only have trouble closing the window. When I clicke the "X" button for closing the window it works.
However, when I call the Monitor.close() method from the main programm that starts the monitor thread, the window just freezes (e.g., it doesn't react on clicking the "X" button) and the thread monitor keeps running. Thus, the main program does not exit.
So, at the moment, I also have to close first the window "manually" by clicking the closing button and then the main program. Not a big issue, but it would be great, if the main program could close the window by itself. Any hints?
Thanks and best regards,
Christian
class Monitor(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
def close(self):
self.root.quit()
self.root.destroy()
def run(self):
self.root=Tkinter.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.close)
self.root.mainloop()
Python Threading and Tk(inter) used in this way do not mix well, as they violate the Tcl/Tk threading model of using Tk just from one thread.
It works great with message passing though, just not with direct calls from a thread. So you need to add some message passing via Queue to this.
Have a look at http://effbot.org/zone/tkinter-threads.htm for an example.

What is the difference between root.destroy() and root.quit()?

In Python using tkinter, what is the difference between root.destroy() and root.quit() when closing the root window?
Is one prefered over the other? Does one release resources that the other doesn't?
root.quit() causes mainloop to exit. The interpreter is still intact, as are all the widgets. If you call this function, you can have code that executes after the call to root.mainloop(), and that code can interact with the widgets (for example, get a value from an entry widget).
Calling root.destroy() will destroy all the widgets and exit mainloop. Any code after the call to root.mainloop() will run, but any attempt to access any widgets (for example, get a value from an entry widget) will fail because the widget no longer exists.
quit() stops the TCL interpreter. This is in most cases what you want, because your Tkinter-app will also stop. It can be a problem, if you e.g. call your app from idle. idle is itself a Tkinker-app, so if you call quit() in your app and the TCL interpreter gets terminated, idle will also terminate (or get confused ).
destroy() just terminates the mainloop and deletes all widgets. So it seems to be safer if you call your app from another Tkinter app, or if you have multiple mainloops."
taken from http://www.daniweb.com/forums/thread66698.html
The tkinter.Tk "quit" method exits the "mainloop" event-handler, and "destroy" destroys all the embedded widgets and only then exits the "mainloop". So is "destroy" the better of the two? Well, sometimes not. If "destroy" fails to destroy all the widgets for some reason, then "mainloop" is never exited and Python locks up. It can be better to just let Python shut things down in an orderly manner at the end of the script.
For example, if you embed a Matplotlib plot in a Tkinter window, that is useful because Matplotlib's own widgets are somewhat clunky to use. Unfortunately, if you then try to close the window by clicking the usual "X" in the title-bar, the window closes alright but leaves Python running. If the script had been started from a terminal, you'd have to mash Ctrl-C for a couple of minutes to get the prompt back. The reason being that the window-close event is bound to "destroy" which does not destroy the Matplotlib objects but leaves them orphaned.
The fix is to bind the window-close event to "quit" instead. But... if the script is started in a Tkinter-based IDE like IDLE, then that creates a new problem in that the window does not close because IDLE holds Tkinter running. So now "destroy" must be added after the mainloop. Finally, all is well.
Below is a minimal example of a Matplotlib plot that can be inverted with a press of a Tkinter button. Its window can be closed without problems. But if the windows-close event had been bound to "destroy" instead of "quit" then a locked-up Python process would remain.
#!/usr/bin/env python3
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
root = tk.Tk()
data, = plt.plot([0,5,3,4,-5,3])
canvas = FigureCanvasTkAgg(plt.gcf(), master=root)
invert = lambda: (data.set_ydata(-data.get_ydata()), canvas.draw())
tk.Button(master=root, text="Invert", command=invert).pack()
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1)
root.protocol("WM_DELETE_WINDOW", root.quit)
root.mainloop()
root.destroy()
Edit: I'll add that by binding the window-close event to both methods, you can avoid adding a line after the "mainloop", should that be desirable for some reason:
root.protocol("WM_DELETE_WINDOW", lambda: (root.quit(), root.destroy()))
My experience with root.quit() and root.destroy() ...
I have a dos python script, which calls a tkinter script (to choose from set of known values from combobox), then returns to the dos script to complete other things.
The TKinter script I've added onto the parent script. I may convert all to tkinter, but a combo works for the time being. It works in the following way:
To get rid of the windows box after selection was implemented, I needed to
1) root.quit() inside the callback function where all my keypresses were being processed.
2) root.destroy() after mainloop to destroy the windows box.
If I used root.destroy() inside the callback, I got an error message saying tkinter objects were no longer accessable.
Without the root.destroy() after mainloop, the windows box STAYED ONSCREEN until the whole parent script had completed.

Categories