{"record":{"id":"9510dc65fb1627db","repo":"pandas-dev/pandas","slug":"only-a-single-expression-is-allowed","errorCode":null,"errorMessage":"only a single expression is allowed","messagePattern":"only a single expression is allowed","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/expr.py","lineNumber":424,"sourceCode":"        self.assigner = None\n\n    def visit(self, node, **kwargs):\n        if isinstance(node, str):\n            clean = self.preparser(node)\n            try:\n                node = ast.fix_missing_locations(ast.parse(clean))\n            except SyntaxError as e:\n                if any(iskeyword(x) for x in clean.split()):\n                    e.msg = \"Python keyword not valid identifier in numexpr query\"\n                raise e\n\n        method = f\"visit_{type(node).__name__}\"\n        visitor = getattr(self, method)\n        return visitor(node, **kwargs)\n\n    def visit_Module(self, node, **kwargs):\n        if len(node.body) != 1:\n            raise SyntaxError(\"only a single expression is allowed\")\n        expr = node.body[0]\n        return self.visit(expr, **kwargs)\n\n    def visit_Expr(self, node, **kwargs):\n        return self.visit(node.value, **kwargs)\n\n    def _rewrite_membership_op(self, node, left, right):\n        # the kind of the operator (is actually an instance)\n        op_instance = node.op\n        op_type = type(op_instance)\n\n        # must be two terms and the comparison operator must be ==/!=/in/not in\n        if is_term(left) and is_term(right) and op_type in self.rewrite_map:\n            left_list, right_list = map(_is_list, (left, right))\n            left_str, right_str = map(_is_str, (left, right))\n\n            # if there are any strings or lists in the expression\n            if left_list or right_list or left_str or right_str:","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/computation/expr.py#L406-L442","documentation":"Raised by visit_Module() when the parsed module body does not contain exactly one expression/statement node. pandas eval/query expects a single expression; if the string parses to multiple statements (e.g., two expressions separated by a semicolon or a newline in a context that produces multiple body nodes), the visitor rejects it. This is distinct from the multi-line eval handling — it fires at the parser level for a single eval call that contains more than one top-level expression.","triggerScenarios":"Calling pd.eval('a; b') (semicolon-separated expressions in a single eval); passing a string that Python's ast.parse splits into multiple body entries unexpectedly.","commonSituations":"Using semicolons to combine expressions inside one eval string; building expressions by joining with ';' programmatically; misformatted strings with stray semicolons.","solutions":["Evaluate one expression per call: call pd.eval twice instead of joining with ';'.","For column assignments in a DataFrame context, use df.eval with newline-separated lines (which are handled as separate single expressions).","Remove stray semicolons or statement separators from the expression string."],"exampleFix":"// before\npd.eval('a + b; c + d')\n\n// after\nr1 = pd.eval('a + b')\nr2 = pd.eval('c + d')","handlingStrategy":"validation","validationCode":"if isinstance(expr, str) and ';' in expr:\n    raise ValueError('eval accepts a single expression; split on \";\" into separate calls')\npd.eval(expr)","typeGuard":null,"tryCatchPattern":"try:\n    pd.eval(expr)\nexcept SyntaxError as e:\n    if 'single expression' in str(e):\n        results = [pd.eval(s) for s in expr.split(';')]\n    else:\n        raise","preventionTips":["Pass one expression per eval call.","Use newlines with df.eval for multi-statement column assignment.","Filter semicolons from programmatically built expressions."],"tags":["pandas","eval","syntax-error","multiple-expressions","parser"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}