[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