This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: atexit.register does not return the registered function.
Type: Stage:
Components: Library (Lib) Versions: Python 2.5
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: georg.brandl Nosy List: georg.brandl, pierre_rouleau
Priority: normal Keywords:

Created on 2006-11-16 16:23 by pierre_rouleau, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (2)
msg30564 - (view) Author: Pierre Rouleau (pierre_rouleau) Date: 2006-11-16 16:23
Since that the decorator syntax is upon us, I think it would be good if atexit.register() was returning the function passed as argument.  This simple change to the library would solve a problem with the use of atexit.register as a decorator (and I can't think of any use case where this change would break any code).

I describe the problem in the following text::


Problem using atexit.register as a decorator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In his April 2005 article titled `Python 2.4
Decorators: Reducing code duplication and consolidating
knowledge`_ , Phillip Eby describes how you can use
`atexit.register()`_ from the standard Python library.
He shows how to use the decorator syntax to register a
function that will execute at program termination. Here
is how it goes::

  @atexit.register
  def goodbye(): 
      print "Goodbye, terminating..."


However, there is one fundamental problem with this:
atexit.register() returns None. Since the above code
corresponds to::


  def goodbye(): 
      print "Goodbye, terminating..."
  goodbye = atexit.register(goodbye)

the code registers goodbye but right after it binds
goodbye to None! You can see this in the following
session::

    >>> import atexit
    >>> @atexit.register
    ... def goodbye():
    ...   print "Goodbye, terminating..."
    ... 
    >>> goodbye()
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    TypeError: 'NoneType' object is not callable
    >>> 
    >>> goodbye
    >>> type(goodbye)
    <type 'NoneType'>
    >>> 

There is two solutions to this problem:

  1. Use another function to register and decorate.
  2. Change atexit.register() in the Python library
     so that it returns the function it registers.

Solution 1 can be implemented right away::

  def atexit_register(fct):
      atexit.register(fct)
      return fct

  @atexit_register
  def goodbye2(): 
      print "Goodbye 2!!"

and it works: it registers the function for execution
at termination but leaves goodbye2 callable::

  >>> def atexit_register(fct):
  ...   atexit.register(fct)
  ...   return fct
  ... 
  >>> @atexit_register
  ... def goodbye2():
  ...   print "Goodbye 2!!"
  ... 
  >>> goodbye2()
  Goodbye 2!!
  >>> goodbye2
  <function goodbye2 at 0x009DD930>
  >>> 

.. References

.. _atexit.register():               http://www.python.org/doc/current/lib/module-atexit.html
.. _Python 2.4 Decorators\: Reducing code duplication and consolidating knowledge:  http://www.ddj.com/184406073
msg30565 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2006-11-16 16:52
This is a reasonable request, I changed atexit.register in rev. 52764 for 2.6.
History
Date User Action Args
2022-04-11 14:56:21adminsetgithub: 44239
2006-11-16 16:23:31pierre_rouleaucreate