Reputation: 1317
Suppose that I define a new persistent class Account as is described in in the ZODB tutorial.
import persistent, ZODB, ZODB.FileStorage, import transaction
class Account(persistent.Persistent):
def __init__(self):
self.balance = 0.0
def deposit(self, amount):
self.balance += amount
def cash(self, amount):
assert amount < self.balance
self.balance -= amount
storage = ZODB.FileStorage.FileStorage('mydata.fs')
db = ZODB.DB(storage)
connection = db.open()
root = connection.root
root.accounts = BTrees.OOBTree.BTree()
root.accounts['account-1'] = Account()
transaction.commit()
After running this script I wrote another script to access the object that I have created.
import persistent, ZODB, ZODB.FileStorage
class Account(persistent.Persistent):
...
storage = ZODB.FileStorage.FileStorage('mydata.fs')
db = ZODB.DB(storage)
connection = db.open()
root = connection.root
print(root.accounts['account-1'])
print(root.accounts['account-1'].balance)
The output of this second script is:
<__main__.Account object at 0x95fbaac>
0.0
But if I comment lines where class Account is defined the output is:
<persistent broken __main__.Account instance '\x00\x00\x00\x00\x00\x00\x00\x02'>
Traceback (most recent call last):
File "test.py", line 24, in <module>
print(root.accounts['account-1'].balance)
AttributeError: 'Account' object has no attribute 'balance'
I guest that object declarations is not attached to the database, so we can't execute or methods that I previously defined in Account. But it is not clear to me if I have some access to attributes in objects where no class definition is found. So my question is: Is there a base data model that can be used to access objects without class definitions in ZODB?
My question is also motivated by the following concerns:
I'm habituated to applications where databases have data models that are separated from application logic. Suppose I incorporate a new module X (defining classes) in a application and then I discovered that X is creating problems in my application. In the classic approach, I always can stop the application and inspect the database without the logic layer to analyze and try to fix the data. And then, start the application again without the module X. But in ZODB I don't found documentation about a data layer that can be used without class definitions.
Upvotes: 0
Views: 515
Reputation: 1121266
The ZODB is built on top of the pickle
module; persistence merely serves to detect changes and to create boundaries between records (so changes to one persistent object do not require writing away the whole object tree).
The data model then is your Python code; pickle
merely stores refences to the class locations, like your Account
, to restore instances from.
When you removed the Account
class definition, all persistent
could give you is a placeholder object for the data. It tells you that pickle
was looking for a class named Account
in the module __main__
, and that the ZODB object id is 2.
You can still inspect the attributes your Account
instance had in the __Broken_state__
attribute of the 'broken' object, if you wanted to introspect that data.
Upvotes: 4