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


_______________________________________________
IDLE-dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/idle-dev

Reply via email to