3

python has atexit module to register functions to run prior to closing of the interpreter. This question nicely why atexit is not called.

I'm wondering if there is an alternative for ipython to register a function prior to exiting something which has been run with %run <name>? Ideally I would like to create a decorator which works registers in either module depending on the interpreter.

Community
  • 1
  • 1
magu_
  • 4,766
  • 3
  • 45
  • 79
  • 1
    There is not something that fires specifically after `%run`, but you could either [define a custom magic](http://ipython.readthedocs.io/en/stable/config/custommagics.html) to do `%run` plus some action, or [provide a post_run_cell callback](http://ipython.readthedocs.io/en/stable/config/callbacks.html) to run after each input is executed. – Thomas K Oct 22 '16 at 09:29

1 Answers1

4

Thanks Thomas K for the good comment. In case he writes an answer I'll accept his. Otherwise this piece of code might benefit somebody else:

# exit_register runs at the end of ipython %run or the end of the python interpreter
try:
    def exit_register(fun, *args, **kwargs):
        """ Decorator that registers at post_execute. After its execution it
        unregisters itself for subsequent runs. """
        def callback():
            fun()
            ip.events.unregister('post_execute', callback)
        ip.events.register('post_execute', callback)


    ip = get_ipython()
except NameError:
    from atexit import register as exit_register


@exit_register
def callback():
    print('I\'m done!')


print('Running')
magu_
  • 4,766
  • 3
  • 45
  • 79
  • 1
    This works great. One thing to add. `atexit.register` can take arguments and keyword arguments. Consider changing `exit_register` to allow this via: `def exit_register(fun, *args, **kwargs)` and `fun(*args, **kwargs)`. – JesterEE Aug 16 '17 at 15:14