Now; - problems using ZODB/ZCatalog in Python
First off, sorry for posting a huge, stinkin' post like this, but instead of posting ten times trying to explain what I do, I post this once and hope somebody can point out what's wrong and I'll leave you all alone, at least for a while. The example is from the Catalog outside Zope-tutorial available at Zope.org. I'm using Zope 2.2.0. This might have been written for Zope 2.1.6. I dunno. I understand the error message, just don't why it is raised. If I should call some form of commit() or close(), where should this be done? And, by the way, does Catalog support different kinds of searches, like matching all the search-words, some, does the order count ? Can this options be set, if any exists? Anyway, thanks for your patience and bandwidth. Thomas import sys sys.path.append('d:\\progra~1\\website\\lib\\python\\') import ZODB import Persistence from Persistence import Persistent from ZODB.FileStorage import FileStorage from Products.ZCatalog.Catalog import Catalog ### create some classes to be persistent class Nobody( Persistent ): def identify( self ): print "I am Nobody!" class Person( Persistent ): def __init__( self, first, name, email, friend=Nobody() ): self.first = first self.name = name self.email = email self.friend= friend def identify( self ): print "I am " + self.first + " " + self.name print "and my Email is " + self.email ### OK, the ZODB-API together with a Catalog-Class class Application: def __init__( self, file='test.fs' ): self.file= file self.db = ZODB.DB( FileStorage( file ) ) self.co = self.db.open() self.root= self.co.root() if self.root.has_key( 'cat' ): self.cat= self.root['cat'] else: self.cat = Catalog() ### This is, how I get it to work self.cat.aq_parent= self.root self.root['cat']= self.cat ### Add indexes to the Catalog-Class ### The names must match the fields of the Person-Class! self.cat.addIndex('first','FieldIndex' ) self.cat.addIndex('name' ,'FieldIndex' ) self.cat.addIndex('email','FieldIndex' ) get_transaction().commit() def storePerson( self, person ): uid= id( person ) print "stored as " + str( uid ) self.root[uid]= person ### Let the Catalog know from this object self.cat.catalogObject( person, uid ) get_transaction().commit() def searchPerson( self, **kw ): r= self.cat.searchResults( kw ) paths= self.cat.paths root = self.root k= [] for i in r: id= i.data_record_id_ k.append( root[paths[id]] ) return k if __name__ == '__main__': a= Application() p1= Person( 'marian','kelc','marian.kelc@ruhr-uni-bochum.de' ) p2= Person( 'tanja', 'kreierhoff','tanja.kreierhoff@web.de', p1 ) p1.friend= p2 a.storePerson( p1 ) a.storePerson( p2 ) ### test2.py a= Application() ### perform searches with keyword-arguments ids= a.searchPerson( name='kelc' ) for i in ids: i.identify() print "Friend is:" i.friend.identify() i.friend.friend.identify() print str( id( i ) ) print str( id( i.friend.friend ) ) stored as 24111488 stored as 16520248 Traceback (innermost last): File "D:\Program Files\Python\Pythonwin\pywin\framework\scriptutils.py", line 307, in RunScript debugger.run(codeObject, __main__.__dict__, start_stepping=0) File "D:\Program Files\Python\Pythonwin\pywin\debugger\__init__.py", line 71, in run _GetCurrentDebugger().run(cmd, globals,locals, start_stepping) File "D:\Program Files\Python\Pythonwin\pywin\debugger\debugger.py", line 533, in run _doexec(cmd, globals, locals) File "D:\Program Files\Python\Pythonwin\pywin\debugger\debugger.py", line 868, in _doexec exec cmd in globals, locals File "D:\python\life\zodb_zcatalog.py", line 84, in ? a= Application() File "D:\python\life\zodb_zcatalog.py", line 28, in __init__ self.db = ZODB.DB( FileStorage( file ) ) File "D:\PROGRA~1\WebSite\lib\python\ZODB\FileStorage.py", line 262, in __init__ lock_file(f) File "D:\PROGRA~1\WebSite\lib\python\ZODB\lock_file.py", line 115, in lock_file raise error, ( StorageSystemError: Could not lock the database file. There must be another process that has opened the file. <p>
Thomas Weholt wrote:
First off, sorry for posting a huge, stinkin' post like this, but instead of posting ten times trying to explain what I do, I post this once and hope somebody can point out what's wrong and I'll leave you all alone, at least for a while.
Let me cut out some of the code to show you what's wrong.
### OK, the ZODB-API together with a Catalog-Class class Application: def __init__( self, file='test.fs' ): self.file= file self.db = ZODB.DB( FileStorage( file ) ) self.co = self.db.open() self.root= self.co.root() (...)
So, every time you create an Application object you're opening Data.fs. Therefore the intention is that only one Application object exists at a time.
if __name__ == '__main__': a= Application() p1= Person( 'marian','kelc','marian.kelc@ruhr-uni-bochum.de' ) p2= Person( 'tanja', 'kreierhoff','tanja.kreierhoff@web.de', p1 ) p1.friend= p2 a.storePerson( p1 ) a.storePerson( p2 )
### test2.py a= Application() (...)
See the problem here? Two Application objects are being created. You might think that the first Application object is automatically deleted when replaced by the second Application object, but there's no guarantee of that. So the problem is that this program is trying to open the database twice. You're not allowed to create multiple FileStorage objects that point to the same file. You are, however, allowed to open multiple connections in different threads to the same file. The fix is easy: remove the offending line. Patched code follows. Good luck!
if __name__ == '__main__': a= Application() p1= Person( 'marian','kelc','marian.kelc@ruhr-uni-bochum.de' ) p2= Person( 'tanja', 'kreierhoff','tanja.kreierhoff@web.de', p1 ) p1.friend= p2 a.storePerson( p1 ) a.storePerson( p2 )
### test2.py # Don't re-open the database. a= Application()
### perform searches with keyword-arguments ids= a.searchPerson( name='kelc' )
for i in ids: i.identify() print "Friend is:" i.friend.identify() i.friend.friend.identify() print str( id( i ) ) print str( id( i.friend.friend ) )
Shane
participants (2)
-
Shane Hathaway -
Thomas Weholt