pandas-dev/pandas · error · SyntaxError

The '@' prefix is not allowed in top-level eval…

Error message

The '@' prefix is not allowed in top-level eval calls.
please refer to your variables by name without the '@' prefix.

What it means

Raised by _check_for_locals() when the '@' prefix appears in an expression at the top level of the eval stack (level==0) or when using the non-pandas parser. The '@' prefix references local/python-space variables and is only supported inside DataFrame.eval / DataFrame.query (which call eval at a non-zero stack level with the pandas parser). At the top-level pd.eval, there is no meaningful local scope to bind, so it is rejected as a SyntaxError.

Solutions

  1. Use DataFrame.eval or DataFrame.query instead of pd.eval when you need '@' variable references: df.eval('@x + col').
  2. If you must use pd.eval, reference variables by name without '@' and pass them via local_dict: pd.eval('x + 1', local_dict={'x': val}).
  3. Switch to the pandas parser if you were on parser='python' and need '@' inside a non-top-level call.

Example fix

// before
x = 5
pd.eval('@x + 1')

// after (option A)
df.eval('@x + col')

// after (option B)
pd.eval('x + 1', local_dict={'x': x})
Defensive patterns

Strategy: validation

Validate before calling

def safe_eval(expr, **kw):
    if '@' in expr:
        # use DataFrame.eval with the frame in scope, or pass local_dict
        raise ValueError('Use df.eval for @-prefixed variables')
    return pd.eval(expr, **kw)

Try / catch

try:
    pd.eval(expr)
except SyntaxError as e:
    if '@' in str(e):
        # switch to DataFrame.eval
        ...

Prevention

When it happens

Trigger: Calling pd.eval('@x + 1') directly instead of df.eval('@x + 1'); calling pd.eval('@x + 1', parser='python') which triggers the 'only supported by the pandas parser' message variant.

Common situations: Confusing top-level pd.eval with DataFrame.eval — users want to reference a Python variable and reach for pd.eval instead of df.eval; tutorials that show df.eval('@var') being copy-pasted into a pd.eval call.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/3ae9cc93364f6012. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/computation/eval.py:175

    return s


def _check_for_locals(expr: str, stack_level: int, parser: str) -> None:
    at_top_of_stack = stack_level == 0
    not_pandas_parser = parser != "pandas"

    if not_pandas_parser:
        msg = "The '@' prefix is only supported by the pandas parser"
    elif at_top_of_stack:
        msg = (
            "The '@' prefix is not allowed in top-level eval calls.\n"
            "please refer to your variables by name without the '@' prefix."
        )

    if at_top_of_stack or not_pandas_parser:
        for toknum, tokval in tokenize_string(expr):
            if toknum == tokenize.OP and tokval == "@":
                raise SyntaxError(msg)


@set_module("pandas")
def eval(
    expr: str | BinOp,  # we leave BinOp out of the docstr bc it isn't for users
    parser: str = "pandas",
    engine: str | None = None,
    local_dict=None,
    global_dict=None,
    resolvers=(),
    level: int = 0,
    target=None,
    inplace: bool = False,
) -> Any:
    """
    Evaluate a Python expression as a string using various backends.

    .. warning::

View on GitHub (pinned to 3b7651241d)