Something like ast.literal_eval to execute variable assignments
<p>I want to do something like:</p>

<pre><code>import ast

def foo(common_stuff, assignment_str):
    common_stuff()
    ast.literal_eval(assignment_str) # assignment to unknown or passed variable

foo('a=1;b=2')
</code></pre>

<p>is this possible in Python?</p>

<p>I am trying to write a general function to (enforce DRY) for this:</p>

<pre><code>    for f, i in zip(task_set, xrange(len(task_set))):
        cd = f.cleaned_data
        t_name = cd.get('t_name')
        start_date = cd.get('start_date')
        end_date = cd.get('end_date')
        project = Project.objects.get(pro_id=p.pro_id)
        task = Task(t_name=t_name, start_date=start_date,
                    end_date=end_date, project=project)
        task.save()
        tasks_list.append(task)
</code></pre>

<p>So I started writing the following:</p>

<pre><code>def save_form(model, formset, foreignkey_assignment, *args){
    for f, i in zip(formset, xrange(len(formset))):
        cd = f.cleaned_data
        get_key_name = lambda x: cd.get(x)
        ast.literal_eval(foreignkey_assignment)
        m = model(**{k:get_key_name(k) for k in args})
        m.save()
}
</code></pre>

<p><code>ast.literal_eval()</code> 'executes' the AST parse tree of an evaluation, and limits this to a strict subset that only allows for standard Python literals. You could take the <a href="https://hg.python.org/cpython/file/v3.5.1/Lib/ast.py#l38" rel="nofollow">source code</a> and add assignment support (where I'd use a separate dictionary to handle names). </p>

<p>You'd have to add <code>Assign</code> and <code>Name</code> node handling (Python 3 version):</p>

<pre><code>def literal_eval(node_or_string, namespace):
    """
    Safely evaluate an expression node or a string containing a Python
    expression.  The string or node provided may only consist of the following
    Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
    sets, booleans, and None.
    """
    if isinstance(node_or_string, str):
        node_or_string = ast.parse(node_or_string, mode='exec')
    if isinstance(node_or_string, ast.Module):
        node_or_string = node_or_string.body
    def _convert(node, ns=None):
        if isinstance(node, (ast.Str, ast.Bytes)):
            return node.s
        elif isinstance(node, ast.Num):
            return node.n
        elif isinstance(node, ast.Tuple):
            return tuple(map(_convert, node.elts))
        elif isinstance(node, ast.List):
            return list(map(_convert, node.elts))
        elif isinstance(node, ast.Set):
            return set(map(_convert, node.elts))
        elif isinstance(node, ast.Dict):
            return dict((_convert(k), _convert(v)) for k, v
                        in zip(node.keys, node.values))
        elif isinstance(node, ast.NameConstant):
            return node.value
        elif isinstance(node, ast.UnaryOp) and \
             isinstance(node.op, (ast.UAdd, ast.USub)) and \
             isinstance(node.operand, (ast.Num, ast.UnaryOp, ast.BinOp)):
            operand = _convert(node.operand)
            if isinstance(node.op, ast.UAdd):
                return + operand
            else:
                return - operand
        elif isinstance(node, ast.BinOp) and \
             isinstance(node.op, (ast.Add, ast.Sub)) and \
             isinstance(node.right, (ast.Num, ast.UnaryOp, ast.BinOp)) and \
             isinstance(node.left, (ast.Num, ast.UnaryOp, ast.BinOp)):
            left = _convert(node.left)
            right = _convert(node.right)
            if isinstance(node.op, ast.Add):
                return left + right
            else:
                return left - right
        elif isinstance(node, ast.Assign) and \
             len(node.targets) == 1 and \
             isinstance(node.targets[0], ast.Name):
                assert isinstance(ns, dict)  # will be None when not top-level
                ns[node.targets[0].id] = _convert(node.value)
                return
        raise ValueError('malformed node or string: ' + repr(node))
    return _convert(node_or_string, namespace)
</code></pre>

<p>Or you could use the <a href="https://newville.github.io/asteval/" rel="nofollow"><code>asteval</code> project</a>, which does exactly that and a little more, supporting simple expressions and assignment, using AST tree interpretation. </p>

python eval variable-assignment literals