[ZODB-Dev] Error message with simple ZODB usage

Tim Peters tim at zope.com
Tue Oct 26 21:36:07 EDT 2004


[kw]
> Oops, my original message was mangled, sorry.

It sure was!  I gave up trying to understand it.  Thanks for repairing it.

> Here's the code again.
> I'm using ZODB 3.3c1, python 2.3.4 on OpenBSD.
>
> I'm new to the ZODB and am writing some simple code to learn how to use
> it; when I try to add and then commit my persistent container, I get the
> message:
>
> No handlers could be found for logger ZODB.FileStorage

This is a Python issue.  ZODB uses Python's logging package, and that's the
kind of message you get if ZODB tries to log a message but you haven't
configured the logging package.  I confess that I find logging configuration
to be nearly incomprehensible -- there's some god-awful config file format
apparently inherited from some Java logging package.  It's very flexible,
but also very obscure.  To pursue that, look at log.ini in the root of a
source distribution, and look inside test.py to see how running the tests
feeds log.ini to the logging package.  log.ini itself contains a URL for
more complete logging config-file docs.

To get you started, just add this near the start of your program:

import logging
logging.basicConfig()

> The testing code is below - and if there are mistakes or breaches of ZODB
> style, corrections are more than welcome.  The "No handlers..." message
> appears when I use the "addBob" argument for the first time, but not
> subsequently.

If you add the logging config above, you'll get this output the first time
you use "addBob":

WARNING:ZODB.FileStorage:Ignoring index for test_people.fs

You get this message because you never close the database explicitly.
Because you don't close it, not all of the in-memory data is written to disk
correctly, and in particular test_people.fs.index is left in a silly on-disk
state after you run your "init" step.  The "addBob" step then detects that
the index file is in a silly state, and warns you that it's going to ignore
it.  Add db.close() whenever you're done with db, and you won't see that
message.

> #!/usr/bin/python
>
> """ Testing ZODB and persistence with a simple example. """
>
> import sys
> sys.path.append('/web/ZopeX3c1/lib/python/')

It's probably more common to fiddle your PYTHONPATH envar, than to hardcode
paths in your code.

> import ZODB, ZODB.FileStorage
> import persistent
>
> class Person(persistent.Persistent):
>
>     def __init__(self):
>         self._type = "Human"

Should really call Persistent.__init__(self).  This protects you in case the
base class constructor does something someday.

> class Man(Person):
>
>     def __init__(self, name):
>         Person.__init__(self)
>         self._name = name
>         self._reason_for_being = "eat, sleep, work."
>
>     def __repr__(self):
>         out = "My name is " + str(self._name) + \
>               " and my raison d'etre is " + str(self._reason_for_being)
>         return out
>
>
> class PeopleDirectory(persistent.Persistent):
>
>     def __init__(self):
>         self._directory = []

Might want to use a PersistentList instead.  Then you don't have to remember
to monkey with _p_changed.  If this list can get large, you'll want to use a
BTree or TreeSet instead.

>     def addPerson(self, person):
>         self._directory.append(person)
>         self._p_changed = 1
>
>     def __repr__(self):
>         out = ""
>         for person in self._directory:
>             out += str(person)
>         return out

That way of building a result string in Python takes time quadratic in
len(self._directory).  If that's large, it can be very slow.  If that can't
be large, it's fine.  If that can be large, here's one linear-time way:

        strings = map(str, self._directory)
        return "".join(strings)

> ...

For the rest, don't forget to do db.close() when you're done with db.  Looks
fine!



More information about the ZODB-Dev mailing list