Python: closure and classes

I need to register a function atexitfor use with a class (see below Foobelow), unfortunately, I don’t have a direct way to clean it up using a method call: another code that I don't control calls Foo.start()and Foo.end(), but sometimes doesn't Foo.end(), if it encounters a mistake, so I need to cleanse myself.

I could use some closing tips in this context:

class Foo:
  def cleanup(self):
     # do something here
  def start(self):
     def do_cleanup():
        self.cleanup()
     atexit.register(do_cleanup)
  def end(self):
     # cleanup is no longer necessary... how do we unregister?
  • Will the closure work properly, for example. c do_cleanup, is the value of the self-binding correct?

  • How can I unregister the atexit () routine?

  • Is there a better way to do this?

edit : this is Python 2.6.5

+3
5

, , , .

cleaners = set()

def _call_cleaners():
    for cleaner in list(cleaners):
        cleaner()

atexit.register(_call_cleaners)

class Foo(object):
  def cleanup(self):
     if self.cleaned:
         raise RuntimeError("ALREADY CLEANED")
     self.cleaned = True
  def start(self):
     self.cleaned = False
     cleaners.add(self.cleanup)
  def end(self):
     self.cleanup()
     cleaners.remove(self.cleanup)
+4

self do_cleanup, , , , , .

atexit.unregister() , , , , , , . , :

class Foo:
  def cleanup(self):
     # do something here
  def start(self):
     self._cleanup = self.cleanup # Need to save the bound method for unregister
     atexit.register(self._cleanup)
  def end(self):
     atexit.unregister(self._cleanup)

, atexit, , ctrl + break SIGABRT Linux.

, __del__, , , , .

, , , Python 2.x. , , - .

+2

shanked , __del__:

import atexit, weakref
class Handler:
    def __init__(self, obj):
        self.obj = weakref.ref(obj)
    def cleanup(self):
        if self.obj is not None:
            obj = self.obj()
            if obj is not None:
                obj.cleanup()

class Foo:
    def __init__(self):
        self.start()

    def cleanup(self):
        print "cleanup"
        self.cleanup_handler = None

    def start(self):
        self.cleanup_handler = Handler(self)
        atexit.register(self.cleanup_handler.cleanup)

    def end(self):
        if self.cleanup_handler is None:
            return
        self.cleanup_handler.obj = None
        self.cleanup()

    def __del__(self):
        self.end()

a1=Foo()
a1.end()
a1=Foo()
a2=Foo()
del a2
a3=Foo()
a3.m=a3

:

  • , .end ; .
  • , ;end; ,
  • , ; atexit
  • , ; atexit

, , , .

. , Foo, , Foo __del__. , .

class Cleanup:
    cleaned = False
    def cleanup(self):
        if self.cleaned:
            return
        print "cleanup"
        self.cleaned = True
    def __del__(self):
        self.cleanup()

class Foo:
    def __init__(self):...
    def start(self):
        self.cleaner = Cleanup()
        atexit.register(Handler(self).cleanup)
    def cleanup(self):
        self.cleaner.cleanup()
    def end(self):
        self.cleanup()

, Cleanup Foo.

+2

, . , , :

    class Foo:
      def __init__(self):
         self.need_cleanup = True
      def cleanup(self):
         # do something here
         print 'clean up'
      def start(self):
         def do_cleanup():
            if self.need_cleanup:
               self.cleanup()
         atexit.register(do_cleanup)
      def end(self):
         # cleanup is no longer necessary... how do we unregister?
         self.need_cleanup = False

, , atexit , " , Python, Python os._exit()."

+1

? , .

(: )

. .

class Foo:
   def cleanup(self):
      pass
   def start(self):
      atexit.register(self.cleanup)

, , , .

+1

Source: https://habr.com/ru/post/1782460/


All Articles