glom API reference

glom gets results.

If there was ever a Python example of “big things come in small packages”, glom might be it.

The glom package has one central entrypoint, glom.glom(). Everything else in the package revolves around that one function.

A couple of conventional terms you’ll see repeated many times below:

  • target - glom is built to work on any data, so we simply refer to the object being accessed as the “target”
  • spec - (aka “glomspec”, short for specification) The accompanying template used to specify the structure of the return value.

Now that you know the terms, let’s take a look around glom’s powerful semantics.

The glom Function

Where it all happens. The reason for the season. The eponymous function, glom.

glom.glom(target, spec, **kwargs)[source]

Access or construct a value from a given target based on the specification declared by spec.

Accessing nested data, aka deep-get:

>>> target = {'a': {'b': 'c'}}
>>> glom(target, 'a.b')
'c'

Here the spec was just a string denoting a path, 'a.b.. As simple as it should be. The next example shows how to use nested data to access many fields at once, and make a new nested structure.

Constructing, or restructuring more-complicated nested data:

>>> target = {'a': {'b': 'c', 'd': 'e'}, 'f': 'g', 'h': [0, 1, 2]}
>>> spec = {'a': 'a.b', 'd': 'a.d', 'h': ('h', [lambda x: x * 2])}
>>> output = glom(target, spec)
>>> pprint(output)
{'a': 'c', 'd': 'e', 'h': [0, 2, 4]}

glom also takes a keyword-argument, default. When set, if a glom operation fails with a GlomError, the default will be returned, very much like dict.get():

>>> glom(target, 'a.xx', default='nada')
'nada'

The skip_exc keyword argument controls which errors should be ignored.

>>> glom({}, lambda x: 100.0 / len(x), default=0.0, skip_exc=ZeroDivisionError)
0.0
Parameters:
  • target (object) – the object on which the glom will operate.
  • spec (object) – Specification of the output object in the form of a dict, list, tuple, string, other glom construct, or any composition of these.
  • default (object) – An optional default to return in the case an exception, specified by skip_exc, is raised.
  • skip_exc (Exception) – An optional exception or tuple of exceptions to ignore and return default (None if omitted). If skip_exc and default are both not set, glom raises errors through.
  • scope (dict) – Additional data that can be accessed via S inside the glom-spec.

It’s a small API with big functionality, and glom’s power is only surpassed by its intuitiveness. Give it a whirl!

Specifier Types

Basic glom specifications consist of dict, list, tuple, str, and callable objects. However, as data calls for more complicated interactions, glom provides specialized specifier types that can be used with the basic set of Python builtins.

class glom.Path(*path_parts)[source]

Path objects specify explicit paths when the default 'a.b.c'-style general access syntax won’t work or isn’t desirable. Use this to wrap ints, datetimes, and other valid keys, as well as strings with dots that shouldn’t be expanded.

>>> target = {'a': {'b': 'c', 'd.e': 'f', 2: 3}}
>>> glom(target, Path('a', 2))
3
>>> glom(target, Path('a', 'd.e'))
'f'

Paths can be used to join together other Path objects, as well as T objects:

>>> Path(T['a'], T['b'])
T['a']['b']
>>> Path(Path('a', 'b'), Path('c', 'd'))
Path('a', 'b', 'c', 'd')

Paths also support indexing and slicing, with each access returning a new Path object:

>>> path = Path('a', 'b', 1, 2)
>>> path[0]
Path('a')
>>> path[-2:]
Path(1, 2)
class glom.Literal(value)[source]

Literal objects specify literal values in rare cases when part of the spec should not be interpreted as a glommable subspec. Wherever a Literal object is encountered in a spec, it is replaced with its wrapped value in the output.

>>> target = {'a': {'b': 'c'}}
>>> spec = {'a': 'a.b', 'readability': Literal('counts')}
>>> pprint(glom(target, spec))
{'a': 'c', 'readability': 'counts'}

Instead of accessing 'counts' as a key like it did with 'a.b', glom() just unwrapped the literal and included the value.

Literal takes one argument, the literal value that should appear in the glom output.

This could also be achieved with a callable, e.g., lambda x: 'literal_string' in the spec, but using a Literal object adds explicitness, code clarity, and a clean repr().

class glom.Spec(spec, scope=None)[source]

Spec objects serve three purposes, here they are, roughly ordered by utility:

  1. As a form of compiled or “curried” glom call, similar to Python’s built-in re.compile().
  2. A marker as an object as representing a spec rather than a literal value in certain cases where that might be ambiguous.
  3. A way to update the scope within another Spec.

In the second usage, Spec objects are the complement to Literal, wrapping a value and marking that it should be interpreted as a glom spec, rather than a literal value. This is useful in places where it would be interpreted as a value by default. (Such as T[key], Call(func) where key and func are assumed to be literal values and not specs.)

Parameters:
  • spec – The glom spec.
  • scope (dict) – additional values to add to the scope when evaluating this Spec

Advanced Specifiers

The specification techniques detailed above allow you to do pretty much everything glom is designed to do. After all, you can always define and insert a function or lambda into almost anywhere in the spec?

Still, for even more specification readability and improved error reporting, glom has a few more tricks up its sleeve.

Conditional access and defaults with Coalesce

Data isn’t always where or what you want it to be. Use these specifiers to declare away overly branchy procedural code.

class glom.Coalesce(*subspecs, **kwargs)[source]

Coalesce objects specify fallback behavior for a list of subspecs.

Subspecs are passed as positional arguments, and keyword arguments control defaults. Each subspec is evaluated in turn, and if none match, a CoalesceError is raised, or a default is returned, depending on the options used.

Note

This operation may seem very familar if you have experience with SQL or even C# and others.

In practice, this fallback behavior’s simplicity is only surpassed by its utility:

>>> target = {'c': 'd'}
>>> glom(target, Coalesce('a', 'b', 'c'))
'd'

glom tries to get 'a' from target, but gets a KeyError. Rather than raise a PathAccessError as usual, glom coalesces into the next subspec, 'b'. The process repeats until it gets to 'c', which returns our value, 'd'. If our value weren’t present, we’d see:

>>> target = {}
>>> glom(target, Coalesce('a', 'b'))
Traceback (most recent call last):
...
CoalesceError: no valid values found. Tried ('a', 'b') and got (PathAccessError, PathAccessError) ...

Same process, but because target is empty, we get a CoalesceError. If we want to avoid an exception, and we know which value we want by default, we can set default:

>>> target = {}
>>> glom(target, Coalesce('a', 'b', 'c'), default='d-fault')
'd-fault'

'a', 'b', and 'c' weren’t present so we got 'd-fault'.

Parameters:
  • subspecs – One or more glommable subspecs
  • default – A value to return if no subspec results in a valid value
  • default_factory – A callable whose result will be returned as a default
  • skip – A value, tuple of values, or predicate function representing values to ignore
  • skip_exc – An exception or tuple of exception types to catch and move on to the next subspec. Defaults to GlomError, the parent type of all glom runtime exceptions.

If all subspecs produce skipped values or exceptions, a CoalesceError will be raised. For more examples, check out the glom Tutorial, which makes extensive use of Coalesce.

glom.SKIP = Sentinel('SKIP')

The SKIP singleton can be returned from a function or included via a Literal to cancel assignment into the output object.

>>> target = {'a': 'b'}
>>> spec = {'a': lambda t: t['a'] if t['a'] == 'a' else SKIP}
>>> glom(target, spec)
{}
>>> target = {'a': 'a'}
>>> glom(target, spec)
{'a': 'a'}

Mostly used to drop keys from dicts (as above) or filter objects from lists.

Note

SKIP was known as OMIT in versions 18.3.1 and prior. Versions 19+ will remove the OMIT alias entirely.

glom.STOP = Sentinel('STOP')

The STOP singleton can be used to halt iteration of a list or execution of a tuple of subspecs.

>>> target = range(10)
>>> spec = [lambda x: x if x < 5 else STOP]
>>> glom(target, spec)
[0, 1, 2, 3, 4]

Target mutation with Assign

New in glom 18.3.0

Most of glom’s API design defaults to safely copying your data. But such caution isn’t always justified.

When you already have a large or complex bit of nested data that you are sure you want to modify in-place, glom has you covered, with the assign() function, and the Assign() specifier type.

glom.assign(obj, path, val)[source]

The assign() function provides convenient “deep set” functionality, modifying nested data structures in-place:

>>> target = {'a': [{'b': 'c'}, {'d': None}]}
>>> _ = assign(target, 'a.1.d', 'e')  # let's give 'd' a value of 'e'
>>> pprint(target)
{'a': [{'b': 'c'}, {'d': 'e'}]}

For more information and examples, see the Assign specifier type, which this function wraps.

class glom.Assign(path, val)[source]

The Assign specifier type enables glom to modify the target, performing a “deep-set” to mirror glom’s original deep-get use case.

Assign can be used to perform spot modifications of large data structures when making a copy is not desired:

# deep assignment into a nested dictionary
>>> target = {'a': {}}
>>> spec = Assign('a.b', 'value')
>>> _ = glom(target, spec)
>>> pprint(target)
{'a': {'b': 'value'}}

The value to be assigned can also be a Spec, which is useful for copying values around within the data structure:

# copying one nested value to another
>>> _ = glom(target, Assign('a.c', Spec('a.b')))
>>> pprint(target)
{'a': {'b': 'value', 'c': 'value'}}

Like many other specifier types, Assign’s destination path can be a T expression, for maximum control:

# changing the error message of an exception in an error list
>>> err = ValueError('initial message')
>>> target = {'errors': [err]}
>>> _ = glom(target, Assign(T['errors'][0].args, ('new message',)))
>>> str(err)
'new message'

Assign has built-in support for assigning to attributes of objects, keys of mappings (like dicts), and indexes of sequences (like lists). Additional types can be registered through register() using the "assign" operation name.

Attempting to assign to an immutable structure, like a tuple, will result in a PathAssignError.

Reducing lambda usage with Call

There’s nothing quite like inserting a quick lambda into a glom spec to get the job done. But once a spec works, how can it be cleaned up?

glom.Call(func, args=None, kwargs=None)[source]

Call specifies when a target should be passed to a function, func.

Call is similar to partial() in that it is no more powerful than lambda or other functions, but it is designed to be more readable, with a better repr.

Parameters:func (callable) – a function or other callable to be called with the target

Call combines well with T to construct objects. For instance, to generate a dict and then pass it to a constructor:

>>> class ExampleClass(object):
...    def __init__(self, attr):
...        self.attr = attr
...
>>> target = {'attr': 3.14}
>>> glom(target, Call(ExampleClass, kwargs=T)).attr
3.14

This does the same as glom(target, lambda target: ExampleClass(**target)), but it’s easy to see which one reads better.

Note

Call is mostly for functions. Use a T object if you need to call a method.

Object-oriented access and method calls with T

glom’s shortest-named feature may be its most powerful.

glom.T = T

T, short for “target”. A singleton object that enables object-oriented expression of a glom specification.

Note

T is a singleton, and does not need to be constructed.

Basically, think of T as your data’s stunt double. Everything that you do to T will be recorded and executed during the glom() call. Take this example:

>>> spec = T['a']['b']['c']
>>> target = {'a': {'b': {'c': 'd'}}}
>>> glom(target, spec)
'd'

So far, we’ve relied on the 'a.b.c'-style shorthand for access, or used the Path objects, but if you want to explicitly do attribute and key lookups, look no further than T.

But T doesn’t stop with unambiguous access. You can also call methods and perform almost any action you would with a normal object:

>>> spec = ('a', (T['b'].items(), list))  # reviewed below
>>> glom(target, spec)
[('c', 'd')]

A T object can go anywhere in the spec. As seen in the example above, we access 'a', use a T to get 'b' and iterate over its items, turning them into a list.

You can even use T with Call to construct objects:

>>> class ExampleClass(object):
...    def __init__(self, attr):
...        self.attr = attr
...
>>> target = {'attr': 3.14}
>>> glom(target, Call(ExampleClass, kwargs=T)).attr
3.14

On a further note, while lambda works great in glom specs, and can be very handy at times, T and Call eliminate the need for the vast majority of lambda usage with glom.

Unlike lambda and other functions, T roundtrips beautifully and transparently:

>>> T['a'].b['c']('success')
T['a'].b['c']('success')

T-related access errors raise a PathAccessError during the glom() call.

Note

While T is clearly useful, powerful, and here to stay, its semantics are still being refined. Currently, operations beyond method calls and attribute/item access are considered experimental and should not be relied upon.

Validation with Check

Sometimes you want to confirm that your target data matches your code’s assumptions. With glom, you don’t need a separate validation step, you can do these checks inline with your glom spec, using Check.

class glom.Check(spec=T, **kwargs)[source]

Check objects are used to make assertions about the target data, and either pass through the data or raise exceptions if there is a problem.

If any check condition fails, a CheckError is raised.

Parameters:
  • spec – a sub-spec to extract the data to which other assertions will be checked (defaults to applying checks to the target itself)
  • type – a type or sequence of types to be checked for exact match
  • equal_to – a value to be checked for equality match (“==”)
  • validate – a callable or list of callables, each representing a check condition. If one or more return False or raise an exception, the Check will fail.
  • instance_of – a type or sequence of types to be checked with isinstance()
  • one_of – an iterable of values, any of which can match the target (“in”)
  • default – an optional default value to replace the value when the check fails (if default is not specified, GlomCheckError will be raised)

Aside from spec, all arguments are keyword arguments. Each argument, except for default, represent a check condition. Multiple checks can be passed, and if all check conditions are left unset, Check defaults to performing a basic truthy check on the value.

Exceptions

glom introduces a few new exception types designed to maximize readability and debuggability. Note that all these errors derive from GlomError, and are only raised from glom() calls, not from spec construction or glom type registration. Those declarative and setup operations raise ValueError, TypeError, and other standard Python exceptions as appropriate.

class glom.PathAccessError(exc, path, part_idx)[source]

This GlomError subtype represents a failure to access an attribute as dictated by the spec. The most commonly-seen error when using glom, it maintains a copy of the original exception and produces a readable error message for easy debugging.

If you see this error, you may want to:

  • Check the target data is accurate using Inspect
  • Catch the exception and return a semantically meaningful error message
  • Use glom.Coalesce to specify a default
  • Use the top-level default kwarg on glom()

In any case, be glad you got this error and not the one it was wrapping!

Parameters:
  • exc (Exception) – The error that arose when we tried to access path. Typically an instance of KeyError, AttributeError, IndexError, or TypeError, and sometimes others.
  • path (Path) – The full Path glom was in the middle of accessing when the error occurred.
  • part_idx (int) – The index of the part of the path that caused the error.
>>> target = {'a': {'b': None}}
>>> glom(target, 'a.b.c')
Traceback (most recent call last):
...
PathAccessError: could not access 'c', part 2 of Path('a', 'b', 'c'), got error: ...
class glom.CoalesceError(coal_obj, skipped, path)[source]

This GlomError subtype is raised from within a Coalesce spec’s processing, when none of the subspecs match and no default is provided.

The exception object itself keeps track of several values which may be useful for processing:

Parameters:
  • coal_obj (Coalesce) – The original failing spec, see Coalesce’s docs for details.
  • skipped (list) – A list of ignored values and exceptions, in the order that their respective subspecs appear in the original coal_obj.
  • path – Like many GlomErrors, this exception knows the path at which it occurred.
>>> target = {}
>>> glom(target, Coalesce('a', 'b'))
Traceback (most recent call last):
...
CoalesceError: no valid values found. Tried ('a', 'b') and got (PathAccessError, PathAccessError) ...
class glom.CheckError(msgs, check, path)[source]

This GlomError subtype is raised when target data fails to pass a Check’s specified validation.

An uncaught CheckError looks like this:

>>> target = {'a': {'b': 'c'}}
>>> glom(target, {'b': ('a.b', Check(type=int))})
Traceback (most recent call last):
...
CheckError: target at path ['a.b'] failed check, got error: "expected type to be 'int', found type 'str'"

If the Check contains more than one condition, there may be more than one error message. The string rendition of the CheckError will include all messages.

You can also catch the CheckError and programmatically access messages through the msgs attribute on the CheckError instance.

Note

As of 2018-07-05 (glom v18.2.0), the validation subsystem is still very new. Exact error message formatting may be enhanced in future releases.

class glom.UnregisteredTarget(op, target_type, type_map, path)[source]

This GlomError subtype is raised when a spec calls for an unsupported action on a target type. For instance, trying to iterate on an non-iterable target:

>>> glom(object(), ['a.b.c'])
Traceback (most recent call last):
...
UnregisteredTarget: target type 'object' not registered for 'iterate', expected one of registered types: (...)

It should be noted that this is a pretty uncommon occurrence in production glom usage. See the Setup and Registration section for details on how to avoid this error.

An UnregisteredTarget takes and tracks a few values:

Parameters:
  • op (str) – The name of the operation being performed (‘get’ or ‘iterate’)
  • target_type (type) – The type of the target being processed.
  • type_map (dict) – A mapping of target types that do support this operation
  • path – The path at which the error occurred.
class glom.PathAssignError(exc, path, dest_name)[source]

This GlomError subtype is raised when an assignment fails, stemming from an assign() call or other Assign usage.

One example would be assigning to an out-of-range position in a list:

>>> assign(["short", "list"], Path(5), 'too far')
Traceback (most recent call last):
...
PathAssignError: could not assign 5 on object at Path(), got error: IndexError(...

Other assignment failures could be due to assigning to an @property or exception being raised inside a __setattr__().

class glom.GlomError[source]

The base exception for all the errors that might be raised from glom() processing logic.

By default, exceptions raised from within functions passed to glom (e.g., len, sum, any lambda) will not be wrapped in a GlomError.

Debugging

Even the most carefully-constructed specfications eventually need debugging. If the error message isn’t enough to fix your glom issues, that’s where Inspect comes in.

class glom.Inspect(*a, **kw)[source]

The Inspect specifier type provides a way to get visibility into glom’s evaluation of a specification, enabling debugging of those tricky problems that may arise with unexpected data.

Inspect can be inserted into an existing spec in one of two ways. First, as a wrapper around the spec in question, or second, as an argument-less placeholder wherever a spec could be.

Inspect supports several modes, controlled by keyword arguments. Its default, no-argument mode, simply echos the state of the glom at the point where it appears:

>>> target = {'a': {'b': {}}}
>>> val = glom(target, Inspect('a.b'))  # wrapping a spec
---
path:   ['a.b']
target: {'a': {'b': {}}}
output: {}
---

Debugging behavior aside, Inspect has no effect on values in the target, spec, or result.

Parameters:
  • echo (bool) – Whether to print the path, target, and output of each inspected glom. Defaults to True.
  • recursive (bool) – Whether or not the Inspect should be applied at every level, at or below the spec that it wraps. Defaults to False.
  • breakpoint (bool) – This flag controls whether a debugging prompt should appear before evaluating each inspected spec. Can also take a callable. Defaults to False.
  • post_mortem (bool) – This flag controls whether exceptions should be caught and interactively debugged with pdb on inspected specs.

All arguments above are keyword-only to avoid overlap with a wrapped spec.

Note

Just like pdb.set_trace(), be careful about leaving stray Inspect() instances in production glom specs.

Setup and Registration

For the vast majority of objects and types out there in Python-land, glom() will just work. However, for that very special remainder, glom is ready and extensible!

glom.register(target_type, **kwargs)[source]

Register target_type so glom() will know how to handle instances of that type as targets.

Parameters:
  • target_type (type) – A type expected to appear in a glom() call target
  • get (callable) – A function which takes a target object and a name, acting as a default accessor. Defaults to getattr().
  • iterate (callable) – A function which takes a target object and returns an iterator. Defaults to iter() if target_type appears to be iterable.
  • exact (bool) – Whether or not to match instances of subtypes of target_type.

Note

The module-level register() function affects the module-level glom() function’s behavior. If this global effect is undesirable for your application, or you’re implementing a library, consider instantiating a Glommer instance, and using the register() and Glommer.glom() methods instead.

class glom.Glommer(**kwargs)[source]

All the wholesome goodness that it takes to make glom work. This type mostly serves to encapsulate the type registration context so that advanced uses of glom don’t need to worry about stepping on each other’s toes.

Glommer objects are lightweight and, once instantiated, provide the glom() method we know and love:

>>> glommer = Glommer()
>>> glommer.glom({}, 'a.b.c', default='d')
'd'
>>> Glommer().glom({'vals': list(range(3))}, ('vals', len))
3

Instances also provide register() method for localized control over type handling.

Parameters:register_default_types (bool) – Whether or not to enable the handling behaviors of the default glom(). These default actions include dict access, list and iterable iteration, and generic object attribute access. Defaults to True.