-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support pickling BuildsFoo #333
Comments
Thanks so much for bringing this to our attention, @Jasha10 ! Fortunately, dataclasses – even dynamically generated ones – already have a >>> from hydra_zen import builds
>>> builds(dict, x=1)().__reduce__()
(<function copyreg._reconstructor(cls, base, state)>,
(types.Builds_dict, object, None),
{'x': 1}) So what this all seems to come down to is: the generated dataclass has to have
See the following: import pickle
import re
from hydra_zen import builds
from omegaconf import OmegaConf
from pytest import raises
def foo(x) -> None:
pass
# Note: reference name and dataclass_name must match
A = builds(foo, dataclass_name="A", populate_full_signature=True)
A.__module__ = __name__
cfg1 = OmegaConf.create(A)
cfg2 = OmegaConf.create(A(x=3))
assert pickle.loads(pickle.dumps(A)) is A
assert pickle.loads(pickle.dumps(A(x=2))) == A(x=2)
assert pickle.loads(pickle.dumps(cfg1)) == cfg1
assert pickle.loads(pickle.dumps(cfg2)) == cfg2 So, unfortunately, I do not think that there is anything we can do to add automatic pickling support for # contents of my_lib/configs.py
from hydra_zen import make_custom_builds_fn
builds = make_custom_builds_fn(zen_module=__name__)
# these can be pickled
Foo = builds(foo, dataclass_name="Foo")
Bar = builds(bar, zen_partial=True, dataclass_name="Bar") I can also take care to ensure that all of hydra-zen's auto-config functionality (e.g. Unfortunately, patterns like In total, hydra_zen can enable users to configure the I am curious to know if this pickle compatibility issue is potentially a big hurdle for compatibility with upcoming omegaconf/Hydra features. Would this be a sticking point that hydra-zen users hit frequently? Footnotes
|
Thanks for the suggested workaround!
Hydra's core functionality (i.e. config composition) does not depend on pickle at all, and I don't foresee any upcoming features that leverage pickle either. As far as current use-cases for pickle+Hydra, here's what comes to mind:
|
Amazingly, from cloudpickle import dumps, loads
from hydra_zen import builds
from omegaconf import OmegaConf
def foo(x) -> None:
pass
A = builds(foo, populate_full_signature=True)
cfg1 = OmegaConf.create(A)
cfg2 = OmegaConf.create(A(x=3))
assert loads(dumps(A)) is A
assert loads(dumps(A(x=2))) == A(x=2)
assert loads(dumps(cfg1)) == cfg1
assert loads(dumps(cfg2)) == cfg2
B = builds(dict, x=builds(int, 2))
cfg3 = OmegaConf.create(B)
cfg4 = OmegaConf.create(B())
assert loads(dumps(B)) is B
assert loads(dumps(cfg1)) == cfg1
assert loads(dumps(cfg2)) == cfg2 |
Yep, |
Just a heads-up that Thanks for the additional context @Jasha10 . I will plan on tackling the following:
|
I was curious to see how from dill import dumps, loads
from dataclasses import dataclass, asdict
from hydra_zen import builds
def foo(x) -> None:
pass
A = builds(foo, populate_full_signature=True)
@dataclass
class B:
a: A
a = A(1)
before = B(a)
save = dumps(before)
after = loads(save)
assert type(before.a) is not type(after.a) # note the "not"!
assert asdict(before) == asdict(after)
assert asdict(after.a) == asdict(before.a) |
Currently it seems pickling the output of
hydra_zen.builds
is not possible:I believe the
PickleError
comes up becauseBuildsFoo
is generated dynamically at runtime.I wonder if it's possible to work around this unpicklability by defining a custom
BuildsFoo.__reduce__
dunder method.(Ref: Stackoverflow question on pickling dynamically generated classes)
The text was updated successfully, but these errors were encountered: