How to extract variables in a Python script without executing it?

In some cases, it is useful to read data from a Python script (which may be from an untrusted source) and extract values โ€‹โ€‹from it.

Although in most cases, a format such as XML / JSON / YAML / TOML is better suited, it is sometimes useful to do this.

How are variable names and values โ€‹โ€‹extracted from a Python script without executing it?
(provided that the construction of the values โ€‹โ€‹does not contain code execution for their creation)

-1
source share
1 answer

This can be done using the Python ast module:

This sample function reads a single named variable from a file.

, , ast.literal_eval().

def safe_eval_var_from_file(mod_path, variable, default=None, *, raise_exception=False):
    import ast
    ModuleType = type(ast)
    with open(mod_path, "r", encoding='UTF-8') as file_mod:
        data = file_mod.read()

    try:
        ast_data = ast.parse(data, filename=mod_path)
    except:
        if raise_exception:
            raise
        print("Syntax error 'ast.parse' can't read %r" % mod_path)
        import traceback
        traceback.print_exc()
        ast_data = None

    if ast_data:
        for body in ast_data.body:
            if body.__class__ == ast.Assign:
                if len(body.targets) == 1:
                    if getattr(body.targets[0], "id", "") == variable:
                        try:
                            return ast.literal_eval(body.value)
                        except:
                            if raise_exception:
                                raise
                            print("AST error parsing %r for %r" % (variable, mod_path))
                            import traceback
                            traceback.print_exc()
    return default


# Example use, read from ourself :)
that_variable = safe_eval_var_from_file(__file__, "this_variable")
this_variable = {"Hello": 1.5, b'World': [1, 2, 3], "this is": {'a set'}}
assert(this_variable == that_variable)
+1

Source: https://habr.com/ru/post/1546522/


All Articles