[Idle-dev] Fwd: atexit handler in IDLE?
Terry Reedy
tjreedy at udel.edu
Thu Jan 17 16:22:50 CET 2013
On 1/17/2013 1:44 AM, Roger Serwy wrote:
> IDLE implicitly runs a script
from the editor window
> as if you specified "-i" when using
> regular python from the command line. Perhaps this behavior needs to be
> documented.
I agree, as part of documenting the behavior itself. It should be
obvious to anyone who understands -i. That is why one can interactively
poke around at the result of running the script and one reason I use
IDLE to develop code. But many (most?) have never used -i from the
command line and have not read the command line documentation carefully.
That said, I wonder: does your proposed patch makes the IDLE behavior
more, or less, like that of "python xxx -i"? If a file, such Steve's, is
run like so, from the command line with -i, does atexit processing
automatically happen before switching to interactive mode, or not?
Perhaps one of you can test. If yes, then IDLE should do the same before
it switches and prints the interactive '>>>' prompt. If not, then I
think IDLE should not either.
In the same circumstance, does ending the file with 'raise SystemExit'
make any difference. In particular, if the answer above is No, is that
answer changed? Does explicit SystemExit get printed as IDLE does now,
or does it abort -i mode?
As with the interpreter, atexit processing should not happen when
running a statement entered in response to the prompt and a patch should
not change this.
My general idea is that we first match normal atexit behavior and be
explicit about any deviations we decide on.
> For what it's worth, this would make the exitfuncs run on the 3.x series:
Only if there is no exception, even SystemExit, whereas at least the
latter and probably any uncaught exception *should* trigger atexit. The
doc says
"Note: The functions registered via this module are not called when the
program is killed by a signal not handled by Python, when a Python fatal
internal error is detected, or when os._exit() is called."
Termination by an exception that is not caught in user code (which *is*
caught by the unwritten try: except: that prints a traceback) seems not
included in the above (unless they internally trigger os._exit, but I am
pretty sure not). In any case adding 1/0 to Steve's file and running
from a command line would tell. In any case:
"At normal program termination (for instance, if sys.exit() is called or
the main module’s execution completes), all functions registered are
called ..."
I do not complete understand the following, or if we can imitate the
behavior it specifies with the undocumented ._run_exitfuncs.
"If an exception is raised during execution of the exit handlers, a
traceback is printed (unless SystemExit is raised) and the exception
information is saved. After all exit handlers have had a chance to run
the last exception to be raised is re-raised."
> diff -r be8e6b81284e Lib/idlelib/run.py
This is current 3.4a0 (default branch)
> --- a/Lib/idlelib/run.py Wed Jan 09 19:00:26 2013 +0100
> +++ b/Lib/idlelib/run.py Thu Jan 17 00:41:22 2013 -0600
> @@ -381,6 +381,8 @@
> if jit:
> self.rpchandler.interp.open_remote_stack_viewer()
> else:
> + import atexit
I assume below that actual patch does import at top of file.
> + atexit._run_exitfuncs()
As long as this works, it is a nice alternative to my idea of forcing
atexit by actually exiting and restarting user process. The question is
where and when to do it. See questions above and below.
> flush_stdout()
Below is the full code of the class Executive(object) method, with
comments and possible changes, and a question.
def runcode(self, code):
global interruptable
try:
self.usr_exc_info = None
interruptable = True
try:
exec(code, self.locals)
finally:
interruptable = False
- except:
#This bare except should be changed to an explicit 'except
BaseException' (unless we decide that is wrong ;-) or rather 'except
BaseException as e' (see below). The code comment below about even
catching SystemExit, which is a BaseException, but not an Exception,
makes the intention clear.
+ except BaseException as e:
self.usr_exc_info = sys.exc_info()
if quitting:
exit()
# quitting is global set False initially and True at 277, 347, 353.
+ atexit._run_exitfuncs()
# perhaps this should be conditioned on isinstance(e, SystemExit)
# but as noted above, I think not
# even print a user code SystemExit exception, continue
print_exception()
jit = self.rpchandler.console.getvar(
"<<toggle-jit-stack-viewer>>")
if jit:
self.rpchandler.interp.open_remote_stack_viewer()
else:
+ atexit._run_exitfuncs()
flush_stdout()
# The else block only runs if there is no exception in the exec statement.
I am guessing that Executive is instantiated in the user process and
that runcode runs usercode in the user process. Is runcode only used for
running scripts? Or is it also used to run interactive statements? If
the latter, does or could runcode know which, so atexit can be run in
the former case but not the latter? In particular, registering an atexit
function should not cause its immediate execution.
--
Terry Jan Reedy
More information about the IDLE-dev
mailing list