PyGlove: symbolic object manipulation for Python, and what it costs you
Manipulating Python Programs
At a glance
- What is it?
- PyGlove turns ordinary Python objects into mutable, rebindable symbolic values so you can drop search into existing code. It is a good fit for AutoML and evolutionary experiments, and a poor fit if you want a stable instrumentation API or cannot tolerate a small team's release cadence.
- Who is it for?
- Adopt PyGlove if you already have a Python program with tunable constants and want to expose them as a search space without rewriting the program around a configuration schema; the @pg.symbolize plus rebind plus pg.iter path is the whole pitch and it holds up for that use.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem PyGlove solves: search spaces inside code you already wrote
Most hyperparameter tooling asks you to describe your model in someone else's schema. You declare a config object, register parameters with a framework, and the framework decides which values are fixed and which are searchable. PyGlove inverts that. You keep writing plain Python classes, add the @pg.symbolize decorator, and the resulting instances become mutable symbolic objects whose fields can be rebound to either concrete values or search-space expressions. The README's Hello example is the whole idea in miniature: a class with a subject argument, an instance bound to 'World', then hello.rebind(subject='PyGlove') to change it, then hello.rebind(subject=pg.oneof(['World', 'PyGlove'])) to turn that same field into a two-value choice. The audience is people doing AutoML, evolutionary computing, and what the README calls machine learning for large teams, where the goal is evolving and sharing ML code rather than tuning a fixed pipeline. It is also pitched at ordinary Python work, listing advanced binding and mutability as daily-programming uses. The honest framing is that PyGlove is a metaprogramming library with a search framework attached, not a search framework with a config library attached.
How the symbolic object model actually works
The mechanism is a mutable symbolic object model layered on top of normal Python objects. Decorating a class with @pg.symbolize makes its instances track their constructor arguments as named, rebindable fields, which is why rebind can take a keyword like subject and return an object of the same class with that field changed. A field can hold a concrete value or a symbolic expression such as pg.oneof([...]), which represents a choice rather than a value. pg.iter then walks the combinations implied by those expressions, yielding concrete instances. In the README example, iterating over a single oneof with two options yields two Hello objects, each of which greets a different subject. Search algorithms sit on top of that same object model: the README describes an API for dropping search into an arbitrary pre-existing Python program, a set of search primitives for defining the search space, a library of ready-to-use search algorithms, a framework for writing new ones, and an interface for handing the search to distributed infrastructure, with Open Source Vizier named as one backend. The topics list on the repository (automl, evolution, meta-learning, symbolic-programming) matches that layering. What the README does not give is a serialization format, a stability guarantee for the symbolic layer, or a description of how rebind interacts with objects that hold references to each other. Those are the places to look in the reference docs before you build on it.
Getting it running, and the smallest useful search loop
Installation is a single command, pip install pyglove, with pip install pyglove --pre for the nightly build. The README claims very few dependencies beyond the Python interpreter, which is worth checking on your own platform since the claim is about the core package and not necessarily every search backend. The minimal program is the Hello class above: define a class, decorate it, construct an instance, call rebind with a concrete value to confirm the field is wired up, then call rebind with pg.oneof and iterate with pg.iter. That three-step sequence is the smallest thing that exercises the symbolic layer end to end, and it is the right first test before you touch a real model. Beyond that, the repository ships worked examples rather than a tutorial: examples/automl/mnist for neural architecture search, examples/automl/nasbench and examples/automl/natsbench for the two NAS benchmarks, and notebook paths under docs/notebooks for evolution (travelling salesman, one-max, symbolic function regression with pg.mutfun), for machine learning (symbolic ML, symbolic neural modeling), and for advanced Python (a sticky-notes mini DSL, interactive SVG components). Those notebooks are where the search primitives and the evolution scheduling API are actually explained. Treat the notebooks as the documentation of record, because the README stops at the greeting example.
Where PyGlove is the wrong tool
The symbolic layer is the cost. Every class you decorate now carries PyGlove semantics, and rebind means an instance's fields are not simply the attributes the constructor set. Code that relies on identity, on pickling, on deepcopy, or on equality behaving the way plain Python objects behave has to be checked rather than assumed, and the README does not discuss any of those interactions. If your program is a library other people import, exposing symbolized classes as part of your public API hands them a dependency on PyGlove's object model, which is a much larger commitment than depending on a config dataclass. If your hyperparameters need to live in a format that other tools already consume, PyGlove's search space is expressed in Python and the README describes no interchange format for exporting it. The project also carries its own disclaimer, quoted from the README: this is not an officially supported Google product. That sentence should be read literally. It means the Alphabet usage described in the README is not a support contract for you, and it means the release cadence is whatever the maintainers can do. The gap between v0.4.4 in January 2024 and v0.4.5 in July 2025 is visible in the release list, and a year and a half between minor tags is a real planning input if you intend to depend on this for anything long-lived.
How it differs from Optuna, Ray Tune and plain config objects
The closest comparison is a hyperparameter optimizer such as Optuna. Optuna's model is a study object and a trial: you write an objective function that calls trial.suggest_float or trial.suggest_categorical, and the sampler decides what to try. The search space lives inside the objective function, and the relationship between a trial and your program is procedural. PyGlove's model is the opposite direction. The search space lives in the objects themselves, a symbolized instance can hold a pg.oneof in a field, and pg.iter materializes concrete instances from it. That means you can take an existing class, decorate it, and get search without restructuring control flow around a trial object, which is what the README means by dropping search into an arbitrary pre-existing Python program. The trade is that PyGlove's approach reaches further into your code: the classes themselves change behavior. A second comparison is a distributed runner such as Ray Tune, which owns scheduling and fault tolerance across a cluster. PyGlove instead exposes an API to interface with distributed infrastructure and names Open Source Vizier as a backend, so the division of labor is that PyGlove defines the space and the algorithms and something else runs the trials. If you already have a working Optuna or Ray Tune pipeline, the migration is not obviously worth it. PyGlove's advantage shows up when the thing being searched is program structure, not a flat list of numbers, which is why the examples are neural architectures and evolved algorithms rather than learning rates.
Maintenance, licensing and what a dependency on PyGlove commits you to
The licence is Apache-2.0, which is a permissive licence with an explicit patent grant and requires you to preserve notices and state changes. That is standard for a Google-originated library and it is not legal advice; if your organization has a policy on the patent termination clause or on notice files, run it past whoever owns that policy. The maintenance picture is the part to weigh. The repository is not archived and the last push is recent, but the tagged releases tell a slower story: v0.4.3 in September 2023, v0.4.4 in January 2024, v0.4.5 in July 2025. Three minor releases in roughly two years, all still on 0.x. For a library that changes how your classes behave, a 0.x version number is a signal that the symbolic object model and the search APIs may still move, and that upgrading is a code change rather than a version bump. The nightly channel, pip install pyglove --pre, exists if you need a fix ahead of a tag, but it also means you are tracking main. The practical commitment is this: pin an exact version, keep the symbolized surface area of your codebase small, and write the test that constructs a symbolized object, rebinds it, and iterates it, because that test is what will tell you whether an upgrade broke the contract you actually depend on.
Editorial conclusion
Adopt PyGlove if you already have a Python program with tunable constants and want to expose them as a search space without rewriting the program around a configuration schema; the @pg.symbolize plus rebind plus pg.iter path is the whole pitch and it holds up for that use. Do not adopt it if you need a stable public API for library consumers, if your hyperparameters must be serialized into a format other tools already read, or if you cannot accept that a 2024 to 2025 gap in tagged releases is normal here. Before committing, verify three things against your own code: that decorating your classes does not break pickling or equality in ways your tests depend on, that the search algorithms you need are actually in the library rather than in the notebooks, and that the Apache-2.0 grant plus the project's own disclaimer that it is not an officially supported Google product is acceptable to whoever signs off on dependencies.
Community notes