I was playing around and found a way to prevent closing of Python when the red key (hang-up key) is pressed. No external modules are needed.
The trick abuses the fact that PyS60 applications run in Active Objects environment and they spend most of their time in Active Scheduler.
As with standard Python, in PyS60 we can set up a function to be called upon interpreter close. This is simply done by assigning a callable to sys.exitfunc or by using the atexit.register() function.
As it turns out, this function is properly called when the red key is pressed. However, this function has no way to tell Python to abort the close. As soon as this function returns, the interpreter will shut down.
So, we have to make sure it will never return. This is simply done by creating an e32.Ao_lock() object and calling its wait() method each time the system wants to shut Python down.
Let me show you some code:
That's all, Python will not close now if you press the red key. It will stay in the wait method forever. The wait method internally re-enables scheduling of Active Objects making your menus and UI controls work again.
import sys, e32
lock = e32.Ao_lock()
sys.exitfunc = lock.wait
One issue is that you have to remember to set the sys.exitfunc to None if you will ever want to close Python. Otherwise, it will be impossible to close it. For example, your exit_key_handler in a standalone app could look like this:
Another issue is that you won't be able to kill Python by pressing C key in task menu. But that may actually be a good thing, depends what kind of app you're writing.
sys.exitfunc = None
I'm not sure how this will behave in a long run because probably every such quit attempt allocates some memory which is freed only when the application finally closes. But this may be so small that it can be ignored.
All tests done using an N73ME / latest firmware / latest PyS60 (1.4.3). Comments are welcome.
--- Added ---
It happened to me that after coming back to the application, the top pane was gone (no icon, no title). The remedy to this was to force a screen refresh in the exitfunc:
import sys, e32, appuifw
lock = e32.Ao_lock()
s = appuifw.app.screen
appuifw.app.screen = 'large'
appuifw.app.screen = s
sys.exitfunc = myexitfunc