Skip to main content

bagofholding

Logo

Binder License Coverage Documentation

DOI Anaconda Last Updated Platform Downloads

bagofholding is designed to be an easy stand-in for pickle serialization for python objects that is transparent, flexible, and suitable for long-term storage.

Advantages

Drop-in replacement

bagofholding stores pickle-able python objects, and can be easily used as a drop-in replacement for pickle serialization:

>>> import bagofholding as boh
>>>
>>> boh.H5Bag.save(42, "file.h5")
>>> print(boh.H5Bag("file.h5").load())
42

Browseable

The contents of stored objects can be browsed without re-instantiating any of the stored data. In the example above, we saw that saving is a class-method, while loading is an instance method. We can grab the "bag" instance and use it to peek at what's inside!

Let's use a slightly more complex object. Readers familiar with pickle will be able to see that the "reduced" structure of the object is captured in the structure of the storage itself:

>>> class MyThing:
...     def __init__(self, answer: int, question: str):
...         self.answer = answer
...         self.question = question
>>>
>>> something = MyThing(42, "still computing...")
>>> boh.H5Bag.save(something, "something.h5")
>>> bag = boh.H5Bag("something.h5")
>>> bag.list_paths()
['object', 'object/args', 'object/args/i0', 'object/constructor', 'object/item_iterator', 'object/kv_iterator', 'object/state', 'object/state/answer', 'object/state/question']

Item-access on the bag object gives access to metadata stored alongside the actual serialized information:

>>> bag["object"]
Metadata(content_type='bagofholding.content.Reducible', qualname='MyThing', module='__main__', version=None, meta=None)

For Jupyter users, we power-up browsing capabilities with a widget under bag.browse() which lets you navigate the tree and see both metadata values and stored types:

Partial-loading

Stored objects can also be re-instantiated in part by leveraging their storage path:

>>> bag.load("object/state/answer")
42

Note that we didn't re-instantiate any part of the object other than this one integer!

This feature is incredibly useful for long-term storage and data transferability, as the loading environment does not need to fully match the saving environment -- only the environment required to load the actual piece of data desired matches. Consider some complex object which, ultimately, contains important or expensive-to-calculate numeric data, e.g. in the form of numpy array. With bagofholding, you can pass this data to a colleague running a different python environment, or come back to it years later. With only bagofholding and numpy installed, the end user can browse through the stored object, access, and load only the valuable numeric data without re-installing the entire original environment.

Version control

In the examples above, we saw that version (and of course package) information is part of the automatically-scraped and stored metadata. This is useful post-facto for knowing what packages need to be installed to properly load your serialized data, and allows us to fail in clean and helpful ways if the loading environment does not match the saving environment. You can also specify at load-time how strict or relaxed bagofholding should be in re-instantiating data if a stored version does not match the currently installed version, giving flexible protection from flawed re-instantiations.

bagofholding also provides tools to act on this data a-priori. To increase the likelihood that stored data will be accessible in the future, you can outlaw any (sub)objects coming from particular modules:

import bagofholding as boh
>>> try:
...     boh.H5Bag.save(something, "will_fail.h5", forbidden_modules=("__main__",))
... except boh.ModuleForbiddenError as e:
...     print(e)
Module '__main__' is forbidden as a source of stored objects. Change the `forbidden_modules` or move this object to an allowed module.

And/or demand that all objects have an identifiable version:

import bagofholding as boh
>>> try:
...     boh.H5Bag.save(something, "will_fail.h5", require_versions=True)
... except boh.NoVersionError as e:
...     print(e)
Could not find a version for __main__. Either disable `require_versions`, use `version_scraping` to find an existing version for this package, or add versioning to the unversioned package.

Of course, metadata for the bag itself is also stored. We saw this in the GUI snapshot above, but it can also be accessed directly by code:

>>> boh.H5Bag.get_bag_info()
H5Info(qualname='H5Bag', module='bagofholding.h5.bag', version='...', libver_str='latest')

(In reality you will see a version code, it is omitted here because this example is executed automatically in the test suite.)

Going further

For a more in-depth look at the above features and to explore other aspects of bagofholding, check out the tutorial notebook.

Object requirements

Under-the-hood, we follow the same patterns as pickle by explicitly invoking many of the same method (__reduce__, __setstate__, etc). Almost any object which can be pickled can be stored using bagofholding. Our requirements are that the object...

  • Must be pickleable
    • You can use the pickle_check method on bag classes to quickly assess this
  • Must not depend on pickle protocol >4
  • Must have a valid boolean response to hasattr for each of the following, and they must conform to python and abc.collections norms if present:
    • __setstate__
    • __setitem__
    • append
    • extend
  • Must have a valid boolean response to hasattr for __metadata__, and this attribute must be castable to a string if present

If your object satisfies these conditions and fails to "bag", please raise a bug report on the issues page!

Metadata

Release files for bagofholding 0.1.14

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bagofholding 0.1.14
File Size Uploaded
bagofholding-0.1.14.tar.gz 45.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bagofholding 0.1.14
File Interpreter ABI Platform
bagofholding-0.1.14-py3-none-any.whl Python 3 none any Details

Total release size: 78.5 kB

Release files / bagofholding-0.1.14.tar.gz

Download URL bagofholding-0.1.14.tar.gz
Size 45.7 kB
Tags Source
SHA-256 checksum
How to use checksums
330d6f492f5db56977cf95f2e43abf869ced84d0aa0935459f1ea2837da48370
BLAKE2b-256 checksum
How to use checksums
5ffb9f19d7e1a987f07ba05c2a69ea744a04aad519cd5c627fb670fdda9114ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / bagofholding-0.1.14-py3-none-any.whl

Download URL bagofholding-0.1.14-py3-none-any.whl
Size 32.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4d77f1f4607300467fbd16e5ba9802705bda87ff6d8c1080b31722069bd0ae1e
BLAKE2b-256 checksum
How to use checksums
fe36b22ddfd68457f5b462e95ab7e297a0ec901d0b4907122d3bffe9ed382e84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.14 This release

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page