pandas-dev/pandas · error · SyntaxError
The '@' prefix is only supported by the pandas parser
Error message
The '@' prefix is only supported by the pandas parser
What it means
The '@' prefix is a pandas-specific extension that lets an expression string reference a Python local variable; it works by token-rewriting '@x' into an internal sentinel via _replace_locals (expr.py:99) during the pandas preparser pass. When you pass parser='python', that preparser is bypassed (PythonExprVisitor uses identity preparser, expr.py:800), so the raw '@' token is meaningless and _check_for_locals rejects it before parsing. The library throws because the python parser has no mechanism to bind '@' to a stack-frame variable.
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 71959b8cb9)
Solutions
- Drop parser='python' and use the default parser='pandas' so the '@' prefix is honored.
- Remove the '@' prefix and inject the variable explicitly via local_dict={'b': b}.
- If you need python-parser semantics, pre-resolve the variable into the string with an f-string (only for trusted, non-user input).
Example fix
// before
pd.eval('a + @b', parser='python')
// after
pd.eval('a + b', parser='python', local_dict={'b': b}) Defensive patterns
Strategy: validation
Validate before calling
def check_at_prefix(expr: str, parser: str) -> None:
import tokenize
from pandas.core.computation.parsing import tokenize_string
if parser != 'pandas':
for toknum, tokval in tokenize_string(expr):
if toknum == tokenize.OP and tokval == '@':
raise ValueError(
"'@' prefix requires parser='pandas'; "
"remove '@' or switch parser"
)
# call before pd.eval:
check_at_prefix(expr, parser) Type guard
def is_at_free_for_python_parser(expr: str, parser: str) -> bool:
return parser == 'pandas' or '@' not in expr Try / catch
try:
pd.eval(expr, parser=parser)
except SyntaxError as e:
if '@' in expr and parser != 'pandas':
# retry with pandas parser or strip locals
pd.eval(expr, parser='pandas')
else:
raise Prevention
- Standardize on parser='pandas' (the default) across the codebase unless you specifically need python-parser semantics.
- When accepting user-supplied filter strings, sanitize or reject '@' unless parser='pandas'.
- Keep '@'-prefixed references inside df.query/df.eval, not bare pd.eval with parser='python'.
When it happens
Trigger: Calling pd.eval('a + @b', parser='python') or df.query('col > @threshold', parser='python'). Anything that combines the literal '@' character in the expression string with parser set to a value other than the default 'pandas'.
Common situations: Switching parser to 'python' to gain strict Python semantics (e.g. floor division) while keeping existing '@'-prefixed variable references copied from a working df.query call. Copy-pasting query expressions between code paths that use different parsers. User-supplied filter strings that happen to contain '@'.
Related errors
- The '@' prefix is not allowed in top-level eval calls. pleas
- only a single expression is allowed
- Variables in expression "{expr}" overlap with builtins: ({s}
- Invalid engine '{engine}' passed, valid engines are {valid_e
- 'numexpr' is not installed or an unsupported version. Cannot
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/a5648fba2cad4ca1.
Report an issue: GitHub.