dumping in destructor

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?KOI8-R?B?7cnU0Q==?=

    dumping in destructor

    I have a class which I want to save it's data automatically on disc,
    when it's destroyed. I have following code:

    from cPickle import dump

    class __Register(obje ct):
    def __init__(self):
    self.dict = {}
    def __del__(self):
    fh = open('aaa', 'w')
    dump(self.dict, fh)
    fh.close()

    g_register = __Register() # global instance. I do not destroy it
    manually, so destructor is called on iterpreter exit

    But when g_register is being destroyed, dump seems to be already dead,
    so I get:

    Exception exceptions.Type Error: "'NoneType' object is not callable" in
    <bound method __Register.__de l__ of <MyWiki.Registe r.__Register object
    at 0x835a74c>ignor ed

    can I somehow save my data from destructor?
  • Marc 'BlackJack' Rintsch

    #2
    Re: dumping in destructor

    On Mon, 20 Oct 2008 01:12:06 -0700, Митя wrote:
    I have a class which I want to save it's data automatically on disc,
    when it's destroyed. I have following code:
    >
    from cPickle import dump
    >
    class __Register(obje ct):
    def __init__(self):
    self.dict = {}
    def __del__(self):
    fh = open('aaa', 'w')
    dump(self.dict, fh)
    fh.close()
    >
    g_register = __Register() # global instance. I do not destroy it
    manually, so destructor is called on iterpreter exit
    The call to `__del__()` is not guaranteed.
    can I somehow save my data from destructor?
    Reliably? No! Change your design, it won't work this way.

    Ciao,
    Marc 'BlackJack' Rintsch

    Comment

    • Hrvoje Niksic

      #3
      Re: dumping in destructor

      Митя <netimen@gmail. comwrites:
      I have a class which I want to save it's data automatically on disc,
      when it's destroyed. I have following code:
      >
      from cPickle import dump
      >
      class __Register(obje ct):
      def __init__(self):
      self.dict = {}
      def __del__(self):
      fh = open('aaa', 'w')
      dump(self.dict, fh)
      fh.close()
      >
      g_register = __Register() # global instance. I do not destroy it
      manually, so destructor is called on iterpreter exit
      In that case you'd be better off using something like:

      import atexit
      ....
      g_register = __Register()
      atexit.register (g_register.sav e)

      'save' being a method that dumps the instance to the file.

      Comment

      • Michele Simionato

        #4
        Re: dumping in destructor

        On Oct 20, 10:12šam, íÉÔÑ <neti...@gmail. comwrote:
        But when g_register is being destroyed, dump seems to be already dead,
        so I get:
        >
        Exception exceptions.Type Error: "'NoneType' object is not callable" in
        <bound method __Register.__de l__ of <MyWiki.Registe r.__Register object
        at 0x835a74c>ignor ed
        >
        can I somehow save my data from destructor?
        The best thing is to use the 'with' statement, but it requires you to
        rewrite all
        of your code. Alternatively you can use the atexit module. I wrote
        once a
        recipe that may be of interest to you:


        Comment

        • =?KOI8-R?B?7cnU0Q==?=

          #5
          Re: dumping in destructor

          Thanks for your answers!

          my g_register is a global register, wich contains all my objects and
          lives all the program lifetime. So 'with' is not appliable. Am I
          right?

          But using atexit sounds to be a good solution

          On Oct 20, 1:58 pm, Michele Simionato <michele.simion ...@gmail.com>
          wrote:
          On Oct 20, 10:12šam, íÉÔÑ <neti...@gmail. comwrote:
          >
          But when g_register is being destroyed, dump seems to be already dead,
          so I get:
          >
          Exception exceptions.Type Error: "'NoneType' object is not callable" in
          <bound method __Register.__de l__ of <MyWiki.Registe r.__Register object
          at 0x835a74c>ignor ed
          >
          can I somehow save my data from destructor?
          >
          The best thing is to use the 'with' statement, but it requires you to
          rewrite all
          of your code. Alternatively you can use the atexit module. I wrote
          once a
          recipe that may be of interest to you:
          >
          http://code.activestate.com/recipes/523007/

          Comment

          • =?KOI8-R?B?7cnU0Q==?=

            #6
            Re: dumping in destructor

            Thank you for your answers!

            my g_register is a global object, and it lives all the program's
            lifetime, so 'with' is not appliable. Am I right?

            I tried to use atexit and wrote following:

            class _Register(objec t):
            def dump(self):
            ....

            class Registerable(ob ject):
            ....

            g_register = _Register()
            atexit.register (g_register.dum p)
            ....
            ....
            g_register.add( Registerable('a a'))

            But now I get:

            cPickle.Picklin gError: Can't pickle <class '__main__.Regis terable'>:
            attribute lookup __main__.Regist erable failed

            Does that mean that by the time of atexit execution my Registerable
            class is already dead?


            Michele Simionato wrote:
            On Oct 20, 10:12�am, ���� <neti....@gmail .comwrote:
            But when g_register is being destroyed, dump seems to be already dead,
            so I get:

            Exception exceptions.Type Error: "'NoneType' object is not callable" in
            <bound method __Register.__de l__ of <MyWiki.Registe r.__Register object
            at 0x835a74c>ignor ed

            can I somehow save my data from destructor?
            >
            The best thing is to use the 'with' statement, but it requires you to
            rewrite all
            of your code. Alternatively you can use the atexit module. I wrote
            once a
            recipe that may be of interest to you:
            >
            http://code.activestate.com/recipes/523007/

            Comment

            • Gabriel Genellina

              #7
              Re: dumping in destructor

              En Mon, 20 Oct 2008 10:01:07 -0200, Митя <netimen@gmail. comescribió:
              Thank you for your answers!
              >
              my g_register is a global object, and it lives all the program's
              lifetime, so 'with' is not appliable. Am I right?
              Why not? You could use a with statement (or try/finally) around your main
              entry point.
              I tried to use atexit and wrote following:
              >
              class _Register(objec t):
              def dump(self):
              ....
              >
              class Registerable(ob ject):
              ....
              >
              g_register = _Register()
              atexit.register (g_register.dum p)
              ...
              ...
              g_register.add( Registerable('a a'))
              >
              But now I get:
              >
              cPickle.Picklin gError: Can't pickle <class '__main__.Regis terable'>:
              attribute lookup __main__.Regist erable failed
              >
              Does that mean that by the time of atexit execution my Registerable
              class is already dead?
              No, at least not due to using atexit. When atexit functions are executed,
              the interpreter is still in a fully working state. From pythonrun.c,
              function Py_Finalize:

              /* The interpreter is still entirely intact at this point, and the
              * exit funcs may be relying on that. In particular, if some thread
              * or exit func is still waiting to do an import, the import machinery
              * expects Py_IsInitialize d() to return true. So don't say the
              * interpreter is uninitialized until after the exit funcs have run.
              * Note that Threading.py uses an exit func to do a join on all the
              * threads created thru it, so this also protects pending imports in
              * the threads created via Threading.
              */

              Probably you have another problem in your code; try to use pickle alone
              (not within atexit) and see what happens.

              --
              Gabriel Genellina

              Comment

              • =?KOI8-R?B?7cnU0Q==?=

                #8
                Re: dumping in destructor

                Thank you! I have already implemented custom load/save operations
                without pickle. And they work fine on atexit.

                Just for information: pickle.dump worked OK when called manually, but
                being called by atexit it produeced the above described error. I don't
                know why.
                On Oct 21, 7:54 am, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
                wrote:
                En Mon, 20 Oct 2008 10:01:07 -0200, §®§Ú§ä§ñ <neti...@gmail. comescribi¨®:
                >
                Thank you for your answers!
                >
                my g_register is a global object, and it lives all the program's
                lifetime, so 'with' is not appliable. Am I right?
                >
                Why not? You could use a with statement (or try/finally) around your main
                entry point.
                >
                >
                >
                >
                >
                I tried to use atexit and wrote following:
                >
                class _Register(objec t):
                def dump(self):
                ....
                >
                class Registerable(ob ject):
                ....
                >
                g_register = _Register()
                atexit.register (g_register.dum p)
                ...
                ...
                g_register.add( Registerable('a a'))
                >
                But now I get:
                >
                cPickle.Picklin gError: Can't pickle <class '__main__.Regis terable'>:
                attribute lookup __main__.Regist erable failed
                >
                Does that mean that by the time of atexit execution my Registerable
                class is already dead?
                >
                No, at least not due to using atexit. When atexit functions are executed,
                the interpreter is still in a fully working state. From pythonrun.c,
                function Py_Finalize:
                >
                /* The interpreter is still entirely intact at this point, and the
                * exit funcs may be relying on that. In particular, if some thread
                * or exit func is still waiting to do an import, the import machinery
                * expects Py_IsInitialize d() to return true. So don't say the
                * interpreter is uninitialized until after the exit funcs have run.
                * Note that Threading.py uses an exit func to do a join on all the
                * threads created thru it, so this also protects pending importsin
                * the threads created via Threading.
                */
                >
                Probably you have another problem in your code; try to use pickle alone
                (not within atexit) and see what happens.
                >
                --
                Gabriel Genellina

                Comment

                Working...