When PersistentDict, when Folder?

2019-06-24 05:10发布

问题:

When should I use a PersistentDict, and when should I use a Folder? What is the difference between them in terms of updates, internal structure, performance, etc?

回答1:

A PersistentMapping is simply a implementation of the python dict type (via the standard library UserDict base class) adjusted for the Persistence semantics of the ZODB; it saves from having to set the _p_changed flag on the nearest class that inherits from Persistent every time you alter the mapping.

A Folder is a much richer type, implementing events, integration with the Zope web interface (ZMI), through-the-web arbitrary properties (attributes with type validation), management of Zope permissions, validation of sub-item ids, import/export, etc. Sub-items folders are stored as attributes on the object itself, with some metadata stored in a private dict on the instance.

Use a Folder when you need any of those extra services (delegation of permissions, id validation, etc), use a PersistentMapping otherwise. Performance wise looking up or storing items is not going to differ much; one is a straight python dict underneath, the other is the instance __dict__ storing the items.

If you are looking for conflict avoidance, you should look into BTrees, the OOBTree class is basically a persistent mapping where values are stored in persistent buckets, avoiding collisions in most cases, and providing conflict resolution for the rest.

If you want Folder semantics with BTree storage semantics, look at Products.BTreeFolder2, and add-on that implements the Folder interfaces but stores sub-objects in a OOBTree instead of as attributes directly on the instances.



回答2:

A PersistentDict (now called a PersistentMapping) is a class that inherits from UserDict.IterableUserDict and persistent.Persistent.

UserDict.IterableUserDict is a built-in python class that simulates an iterable dictionary and persistent.Persistent is a Zope class that enables an instance of itself to be saved in the ZODB.

So a PersistentDict (or PersistentMapping) is basically a dictionary that can be stored as an object in the ZODB.

Normal dictionaries cannot be stored as separate objects in the ZODB. They have to be attributes of some class that inherits from persistent.Persistent.

PersistentDict stores its keys and values inside an actual dictionary (the data attribute).

A PersistentDict cannot be added through the ZMI and I think it's intended mostly for the special case where you want to store a dictionary directly in the zodb.

With a Folder I guess you mean the folder in zope.container.folder. A Folder stores it's children inside an OOBTree object, which is a container that can hold large amounts of objects.

When you want a container that contains instances of other content types, then you should rather go with a Folder.

A Folder has interfaces that a PersistentDict doesn't have and these interfaces may be required for certain adapters or other components to work. For example, the ContainerModified event will only fire when a Folder was modified, not a PersistentDict. There might be all kinds of gotchas like these if you use a PersistentDict as a general purpose Folder.

When it comes to performance, a dictionary will usually be faster until the keyspace becomes very large. Then the scales are tipped towards the OOBTree.