def get_macro_obj_from_id(macro_id, macro=None):
    '''Get a processed macro from the macro id.  Raises an exception
    on error.  Assumes valid input.  Incrments the view counter
    for this macro.'''

    # First check memcache for a processed macro object:
    macro_obj = memcache.get(MACRO_PROC_KEY % macro_id)
    if not macro_obj:
        # Nothing from memcache, load from data store.
        if not macro:
            saved_macro_entity = SavedMacroOps.get_macro_entity(macro_id)
            # If saved_macro_entity is still none, we failed
            # in the datastore.
            if saved_macro_entity is None:
                raise NoInputError("Macro id '%s' not found." % macro_id)
            macro = saved_macro_entity.macro

        # Process the macro, lazily importing.
        from macro.interpret.interpreter import MacroInterpreter
        macro_obj = MacroInterpreter().interpret_macro(macro)

        # Save macro in memcached.
        memcache.add(MACRO_PROC_KEY % macro_id,
                     macro_obj,
                     MEMCACHED_MACRO_PROC)
    return macro_obj