dumbdbm module broken in Python2.3?
Changjune Kim
juneaftn at REMOVETHIShanmail.net
Thu Mar 13 10:35:01 EST 2003
More information about the Python-list mailing list
Thu Mar 13 10:35:01 EST 2003
- Previous message (by thread): dumbdbm module broken in Python2.3?
- Next message (by thread): lambda question
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
"Jane Austine" <janeaustine50 at hotmail.com> wrote in message news:ba1e306f.0303111337.72a696c7 at posting.google.com... > I used shelve.py and it falls back on dumbdbm when no > possible alternatives are found on the system. > > I found this error, which is recurrent and deterministic: > > Exception exceptions.AttributeError: "'NoneType' object has no > attribute 'error'" in <bound method _Database.__del__ of > <dumbdbm._Database instance at 0x820c71c>> ignored > > The problem seems to reside in the __del__ of dumbdbm._Database: > > class _Database: > ... > def __del__(self): > if self._index is not None: > self._commit() > ... > def _commit(self): > try: _os.unlink(self._bakfile) > except _os.error: pass > try: _os.rename(self._dirfile, self._bakfile) > except _os.error: pass > f = _open(self._dirfile, 'w', self._mode) > for key, (pos, siz) in self._index.items(): > f.write("%s, (%s, %s)\n" % (`key`, `pos`, `siz`)) > f.close() > > My investigation showed that the error was from _commit. When > it was called, _os or _open was both None. And the exception > catch didn't work quite safely cause its in the "except" clause. > > The reason I suspect is when the time that _Database.__del__ was > called the os module(which is imported as _os) is already removed out. > > I changed the code as: > > def _commit(self): > global _os > if _os is None: > import os as _os > import __builtin__ > _open = __builtin__.open > try: _os.unlink(self._bakfile) > except _os.error: pass > try: _os.rename(self._dirfile, self._bakfile) > except _os.error: pass > ...... > > Now it works without any problems, AFAIK. > > Am I right on the track? > > Jane You should be using shelve with auto-garbage-collection. A safer and proper way is close shelve explicitly. This is a minimal case code for the same kind of error: <code> import types import types as _types class A: def __del__(self): try: _types.IntType except: print "error from A" class B: def __del__(self): try: types.IntType except: print "error from B" foobar=(A(),B()) </code> This results in "error from A" only. Why? See what happens with -v option: ... # clear __builtin__._ # clear sys.path # clear sys.argv # clear sys.ps1 # clear sys.ps2 # clear sys.exitfunc # clear sys.exc_type # clear sys.exc_value # clear sys.exc_traceback # clear sys.last_type # clear sys.last_value # clear sys.last_traceback # restore sys.stdin # restore sys.stdout # restore sys.stderr # cleanup __main__ error from A # cleanup[1] __future__ # cleanup[1] site # cleanup[1] types # cleanup[1] sitecustomize # cleanup[1] nt # cleanup[1] signal ... # cleanup[2] os # cleanup sys # cleanup __builtin__ # cleanup ints: 2 unfreed ints in 1 out of 1 block # cleanup floats __main__ is cleared and _types is removed as __main__ is cleaned up. However, types.IntType still exists since "types" is cleaned up much later. One way around it is: def __del__(self,_types=_types): and you get no errors at all. Still the best way is explicitly del-ing what you don't need anymore. Explicit is better than implicit in Python world.
- Previous message (by thread): dumbdbm module broken in Python2.3?
- Next message (by thread): lambda question
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list