{"id":113038,"date":"2026-06-28T20:08:16","date_gmt":"2026-06-28T14:38:16","guid":{"rendered":"https:\/\/www.guvi.in\/blog\/?p=113038"},"modified":"2026-06-28T20:08:19","modified_gmt":"2026-06-28T14:38:19","slug":"python-eval-explained-and-how-it-works","status":"publish","type":"post","link":"https:\/\/www.guvi.in\/blog\/python-eval-explained-and-how-it-works\/","title":{"rendered":"Python eval() Explained: How It Works and When to Use It"},"content":{"rendered":"\n<p>Python\u2019s eval() lets you turn a string into executable code at runtime. eval (&#8220;3 + 4&#8221;) returns 7, showcasing the language\u2019s expressiveness and flexibility. This dynamic evaluation powers simple calculators, configurable expression-driven systems, and lightweight code generation tools without building a custom parser.&nbsp;<\/p>\n\n\n\n<p>Use it carefully, though: executing untrusted strings is a serious security risk and can be mitigated by input validation, restricted globals, or safer alternatives like ast.literal_eval for simple literals.<\/p>\n\n\n\n<p>In this article, we will walk through everything you need to understand about python eval(). We will cover its syntax and three parameters, walk through practical code examples for different use cases, explain the security risks clearly and honestly, show you how to restrict its execution environment, and introduce the safer alternatives you should reach for first.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">TL;DR&nbsp;<\/h2>\n\n\n\n<ul>\n<li>eval() executes a string containing a Python expression and returns its result; use it for dynamic expression evaluation.<\/li>\n\n\n\n<li>Signature: eval(expression, globals=None, locals=None). expression must be an expression (not statements). globals\/locals control the execution namespace.<\/li>\n\n\n\n<li>Dangerous with untrusted input&nbsp; it can run arbitrary code. Prefer ast.literal_eval, json.loads, or operator-based dispatch when possible.<\/li>\n\n\n\n<li>You can limit risk by providing restricted globals\/locals (e.g., {&#8220;<em>_builtins<\/em>_&#8221;: {}}) and validating input, but sandboxing eval perfectly is hard.<\/li>\n\n\n\n<li>Use exec() for statements (no return value) and eval() for expressions (returns value); both carry similar security concerns.<\/li>\n<\/ul>\n\n\n\n<div class=\"guvi-answer-card\" style=\"margin: 40px 0;\">\n\n  <div style=\"\n    position: relative;\n    background: linear-gradient(135deg, #f0fff4, #e6f7ee);\n    border: 1px solid #cfeedd;\n    padding: 26px 24px 22px 24px;\n    border-radius: 14px;\n    font-family: Arial, sans-serif;\n    box-shadow: 0 6px 16px rgba(0,0,0,0.05);\n  \">\n\n    <!-- Top accent -->\n    <div style=\"\n      position: absolute;\n      top: 0;\n      left: 0;\n      height: 6px;\n      width: 100%;\n      background: linear-gradient(to right, #099f4e, #6dd5a3);\n      border-radius: 14px 14px 0 0;\n    \"><\/div>\n\n    <!-- Title -->\n    <h3 style=\"\n      margin: 10px 0 12px 0;\n      color: #099f4e;\n      font-size: 20px;\n    \">\n      What Is eval() in Python?\n    <\/h3>\n\n    <!-- Content -->\n    <p style=\"\n      margin: 0;\n      color: #2f4f3f;\n      font-size: 16px;\n      line-height: 1.7;\n    \">\n      <code>eval()<\/code> is a built-in Python function that takes a string containing a valid Python expression, interprets it as Python code, evaluates it, and returns the resulting value. It accepts an expression string along with optional <code>globals<\/code> and <code>locals<\/code> dictionaries that control the variables, functions, and objects accessible during evaluation. While <code>eval()<\/code> can be useful for dynamically evaluating expressions, it should be used with caution because executing untrusted input can create serious security risks.\n    <\/p>\n\n  <\/div>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The Syntax of Python eval()<\/strong><\/h2>\n\n\n\n<ol>\n<li><strong>Expression (required)<\/strong><\/li>\n<\/ol>\n\n\n\n<p>The first parameter, expression, is required and must be a string containing a valid <a href=\"https:\/\/www.guvi.in\/blog\/beginner-roadmap-for-python-basics-to-web-frameworks\/\" target=\"_blank\" rel=\"noreferrer noopener\">Python <\/a>expression. eval() accepts expressions that produce a value (for example, 3 + 4, len(&#8220;hello&#8221;), or x * 2).&nbsp;<\/p>\n\n\n\n<p>It does not accept statements; passing a statement such as x = 5 or a for loop will raise a SyntaxError.<\/p>\n\n\n\n<ol start=\"2\">\n<li><strong>Globals (optional)<\/strong><\/li>\n<\/ol>\n\n\n\n<p>The second parameter, globals, is an optional dictionary that defines the global namespace available to the evaluated expression. If provided, it controls which global variables and functions the expression can access. If not provided, eval() uses the calling code\u2019s current global scope.<\/p>\n\n\n\n<ol start=\"3\">\n<li><strong>Locals (optional)<\/strong><\/li>\n<\/ol>\n\n\n\n<p>The third parameter, locals, is an optional dictionary (or mapping) that defines the local namespace for the evaluation. It works like globals but for local names. If locals is omitted, eval() uses the calling code\u2019s current local scope (or the globals dict if only two arguments are given).<\/p>\n\n\n\n<ol start=\"4\">\n<li><strong>Default behavior and safety note<\/strong><\/li>\n<\/ol>\n\n\n\n<p>If neither globals nor locals is passed, eval() executes the expression using the current global and local scope of the caller.&nbsp;<\/p>\n\n\n\n<p>These namespace parameters are the main tool for restricting what the evaluated code can access and so are important for making eval() safer (for example, by supplying a limited globals dict or using safer alternatives like ast.literal_eval when appropriate).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How eval() Actually Works Internally<\/strong><\/h2>\n\n\n\n<p>Here it is rewritten as step-wise subheadings, with each step concise and clear.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 1: Parse the string<\/strong><\/h3>\n\n\n\n<ul>\n<li>Python checks the string for valid Python syntax.<\/li>\n\n\n\n<li>If the string contains invalid syntax, Python raises a SyntaxError and stops before any execution.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 2: Compile to bytecode<\/strong><\/h3>\n\n\n\n<ul>\n<li>The parsed expression is converted into Python bytecode, the same intermediate form the interpreter uses for regular code.<\/li>\n\n\n\n<li>This compilation prepares the code for execution.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 3:&nbsp; Execute the bytecode<\/strong><\/h3>\n\n\n\n<ul>\n<li>The bytecode is executed by the Python virtual machine.<\/li>\n\n\n\n<li>You can supply globals and locals dictionaries to control the execution namespace.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 4: Return the result<\/strong><\/h3>\n\n\n\n<ul>\n<li>The value produced by executing the expression is returned to the caller.<\/li>\n\n\n\n<li>Example: eval(&#8220;3 + 4&#8221;) returns 7.<\/li>\n<\/ul>\n\n\n\n<p>Notes on usage and safety<\/p>\n\n\n\n<ul>\n<li>evaluates expressions only (not full statements like loops or def), while exec() can run statements.<\/li>\n\n\n\n<li>Running eval() on untrusted input is dangerous because it can execute arbitrary code; prefer safer alternatives (e.g., ast.literal_eval for literals) or strong input validation.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Basic Examples of eval()<\/strong><\/h2>\n\n\n\n<p>Starting with the simplest use case makes the function&#8217;s behavior immediately clear.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Basic arithmetic expressions\n\nresult1 = eval(\"3 + 4\")\n\nprint(result1)&nbsp; &nbsp; &nbsp; &nbsp; # Output: 7\n\nprint(type(result1))&nbsp; # Output: &lt;class 'int'&gt;\n\nresult2 = eval(\"10 * 2.5\")\n\nprint(result2)&nbsp; &nbsp; &nbsp; &nbsp; # Output: 25.0\n\nresult3 = eval(\"2 ** 8\")\n\nprint(result3)&nbsp; &nbsp; &nbsp; &nbsp; # Output: 256\n\n# String operations\n\nresult4 = eval(\"'Hello' + ' ' + 'World'\")\n\nprint(result4)&nbsp; &nbsp; &nbsp; &nbsp; # Output: Hello World\n\n# Boolean expressions\n\nresult5 = eval(\"5 &gt; 3 and 10 &lt; 20\")\n\nprint(result5)&nbsp; &nbsp; &nbsp; &nbsp; # Output: True\n\n# Using Python built-in functions inside eval\n\nresult6 = eval(\"len('Python')\")\n\nprint(result6)&nbsp; &nbsp; &nbsp; &nbsp; # Output: 6\n\nresult7 = eval(\"max(10, 25, 7, 18)\")\n\nprint(result7)&nbsp; &nbsp; &nbsp; &nbsp; # Output: 25<\/code><\/pre>\n\n\n\n<p>Notice something important in the output of the first example: it returns an actual integer, not a string. It does not just interpret the expression visually. It fully evaluates it and returns the native Python type of the result. This is fundamentally different from simply printing a string that looks like a number.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Using eval() With Variables in Scope<\/strong><\/h2>\n\n\n\n<p>When globals and locals are not specified, eval() has access to all variables in the current scope. This allows expressions to reference variables defined in the surrounding code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>x = 10\n\ny = 20\n\nz = 5\n\n# eval() can access variables from the current scope\n\nresult = eval(\"x + y * z\")\n\nprint(result)&nbsp; &nbsp; # Output: 110&nbsp; (10 + 20*5 = 110)\n\n# Using variables in comparisons\n\nname = \"Alice\"\n\nresult2 = eval(\"name.upper() + ' is learning Python'\")\n\nprint(result2) &nbsp; # Output: ALICE is learning Python\n\n# Calling functions defined in the current scope\n\ndef square(n):\n\n&nbsp;&nbsp;&nbsp;&nbsp;return n ** 2\n\nresult3 = eval(\"square(x) + y\")\n\nprint(result3) &nbsp; # Output: 120&nbsp; (100 + 20)<\/code><\/pre>\n\n\n\n<p>The fact that it silently inherits the full current namespace when no globals or locals are provided is precisely what makes it dangerous with untrusted input, but also what makes it convenient for quick internal use cases.<\/p>\n\n\n\n<div style=\"background-color: #099f4e; border: 3px solid #110053; border-radius: 12px; padding: 18px 22px; color: #FFFFFF; font-size: 18px; font-family: Montserrat, Helvetica, sans-serif; line-height: 1.6; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 750px;\">\n  <strong style=\"font-size: 22px; color: #FFFFFF;\">\ud83d\udca1 Did You Know?<\/strong>\n  <p style=\"margin-top: 14px; margin-bottom: 0;\">\n    Python\u2019s <strong style=\"color: #FFFFFF;\">eval()<\/strong> function does much more than evaluate text\u2014it first compiles the supplied expression into <strong style=\"color: #FFFFFF;\">Python bytecode<\/strong> and then executes it inside the current Python virtual machine. Because of this, the result is returned as a native Python object such as an <strong style=\"color: #FFFFFF;\">integer<\/strong>, <strong style=\"color: #FFFFFF;\">float<\/strong>, <strong style=\"color: #FFFFFF;\">list<\/strong>, or other data type, rather than a string. While this makes <strong style=\"color: #FFFFFF;\">eval()<\/strong> convenient for internal tools, calculators, and dynamic configuration expressions, it also makes it dangerous when used with untrusted input. Since eval() can access the current execution scope by default, improper use is one of the most common causes of <strong style=\"color: #FFFFFF;\">remote code execution (RCE)<\/strong> vulnerabilities in Python applications.\n  <\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Using eval() With globals and locals<\/strong><\/h2>\n\n\n\n<p>The second and third parameters give you explicit control over what the evaluated expression can see and access.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Providing specific variables through locals\n\nexec_locals = {'a': 10, 'b': 20}\n\nresult = eval(\"a * b\", {}, exec_locals)\n\nprint(result)&nbsp; &nbsp; # Output: 200\n\n# The expression cannot access variables outside exec_locals\n\nx = 999\n\ntry:\n\n&nbsp;&nbsp;&nbsp;&nbsp;result = eval(\"x + a\", {}, exec_locals)\n\nexcept NameError as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;print(f\"Error: {e}\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Error: name 'x' is not defined\n\n# Providing math functions through globals\n\nimport math\n\nmath_globals = {\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"sin\": math.sin,\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"cos\": math.cos,\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"pi\": math.pi,\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"__builtins__\": {} &nbsp; # disable built-in functions\n\n}\n\nresult = eval(\"sin(pi \/ 2)\", math_globals)\n\nprint(result)&nbsp; &nbsp; # Output: 1.0\n\nresult2 = eval(\"cos(0)\", math_globals)\n\nprint(result2) &nbsp; # Output: 1.0<\/code><\/pre>\n\n\n\n<ol>\n<li><strong>The eval() function lets you control the environment in which the expression runs. You can use the optional globals and locals dictionaries to define which variables and functions eval() can access. globals provides the global variables for the evaluation.<\/strong><\/li>\n\n\n\n<li>&nbsp;Locals provides the local variables for the evaluation. If you do not provide globals and locals, eval() uses the current environment.<\/li>\n\n\n\n<li>Passing an empty dictionary {} as globals and a specific dictionary as locals creates an isolated sandbox where the expression can only see exactly what you explicitly provided.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Practical Use of eval Case 1: A Dynamic Calculator<\/strong><\/h2>\n\n\n\n<p>One of the most common legitimate uses of eval() is building a calculator that accepts mathematical expressions from users or configuration files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def calculate(expression):\n\n&nbsp;&nbsp;&nbsp;&nbsp;allowed_chars = set(\"0123456789 +-*\/().**% \")\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Basic validation: only allow safe characters\n\n&nbsp;&nbsp;&nbsp;&nbsp;if not all(c in allowed_chars for c in expression):\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(f\"Invalid characters in expression: {expression}\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Restricted namespace: only math operations allowed\n\n&nbsp;&nbsp;&nbsp;&nbsp;safe_globals = {\"__builtins__\": {}}\n\n&nbsp;&nbsp;&nbsp;&nbsp;safe_locals = {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"abs\": abs,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"round\": round,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"pow\": pow,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"max\": max,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"min\": min,\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;try:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = eval(expression, safe_globals, safe_locals)\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result\n\n&nbsp;&nbsp;&nbsp;&nbsp;except Exception as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(f\"Could not evaluate expression: {e}\")\n\n# Testing the calculator\n\nexpressions = &#91;\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"2 + 3 * 4\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"100 \/ 4 - 5\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"2 ** 10\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"abs(-42)\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"round(3.14159, 2)\"\n\n]\n\nfor expr in expressions:\n\n&nbsp;&nbsp;&nbsp;&nbsp;print(f\"{expr} = {calculate(expr)}\")\n\nOutput:\n\n2 + 3 * 4 = 14\n\n100 \/ 4 - 5 = 20.0\n\n2 ** 10 = 1024\n\nabs(-42) = 42\n\nround(3.14159, 2) = 3.14<\/code><\/pre>\n\n\n\n<p>For internal tools processing trusted input, eval() works well as a calculator alternative. The alternative is writing your own expression parser, which is significantly more work for the same result.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Practical Use of eval Case&nbsp; 2: Dynamic Configuration and Runtime Code<\/strong><\/h2>\n\n\n\n<p>eval() is also useful when you need to evaluate expressions that are not known until runtime, such as those loaded from configuration files or generated by other parts of your program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Simulating a configuration system with dynamic expressions\n\nconfig = {\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"discount_rate\": \"0.15\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"tax_formula\": \"price * 0.08\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;\"bonus_formula\": \"base_salary * 0.10 + 500\"\n\n}\n\n# Evaluate tax formula with a specific price\n\nprice = 200\n\ntax = eval(config&#91;\"tax_formula\"])\n\nprint(f\"Tax on ${price}: ${tax}\")&nbsp; &nbsp; # Tax on $200: $16.0\n\n# Evaluate bonus formula\n\nbase_salary = 50000\n\nbonus = eval(config&#91;\"bonus_formula\"])\n\nprint(f\"Bonus: ${bonus}\")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Bonus: $5500.0\n\n# Dynamic operation selection\n\ndef apply_operation(values_str, operation):\n\n&nbsp;&nbsp;&nbsp;&nbsp;values = eval(values_str)&nbsp; &nbsp; &nbsp; &nbsp; # e.g., \"&#91;5, 2, 9, 1]\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;result = eval(f\"{operation}({values_str})\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;return result\n\nprint(apply_operation(\"&#91;5, 2, 9, 1]\", \"max\"))&nbsp; # 9\n\nprint(apply_operation(\"&#91;5, 2, 9, 1]\", \"min\"))&nbsp; # 1\n\nprint(apply_operation(\"&#91;5, 2, 9, 1]\", \"sum\"))&nbsp; # 17<\/code><\/pre>\n\n\n\n<p>Configuration systems, templating engines, and developer tools occasionally require constructing and executing code at runtime. This pattern makes sense when the code comes from a controlled source, like a configuration file you wrote. It becomes dangerous when the input comes from users or external systems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The Security Risk: Why eval() Can Be Dangerous<\/strong><\/h2>\n\n\n\n<p>This is the section that every beginner must read carefully. eval() is one of the most dangerous functions in Python when used with untrusted input, and the risk is real, not theoretical.<\/p>\n\n\n\n<p>While eval() is powerful, it carries risks. Never use eval() with untrusted input. If you let a user provide the string for eval(), they could type malicious code. This code could delete files from your system.<\/p>\n\n\n\n<p>Here is a concrete example of what a malicious user could pass to an unprotected eval():<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># DANGEROUS: Never do this in production code\n\nuser_input = input(\"Enter expression: \")\n\nresult = eval(user_input) &nbsp; # SECURITY VULNERABILITY\n\nIf a user types any of the following, the results could be catastrophic:\n\n# User inputs that could cause serious damage:\n\n# Delete all files in current directory\n\n\"__import__('os').system('rm -rf *')\"\n\n# Read sensitive files from the system\n\n\"open('\/etc\/passwd').read()\"\n\n# Access environment variables containing secrets\n\n\"__import__('os').environ\"\n\n# Execute arbitrary shell commands\n\n\"__import__('subprocess').run(&#91;'ls', '-la'])\"<\/code><\/pre>\n\n\n\n<p>Python&#8217;s eval() automatically inserts a reference to the dictionary of builtins into globals before parsing the expression. A malicious user could exploit this behavior by using the built-in function _import__() to get access to dangerous system functionality.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to Restrict eval() for Safer Use<\/strong><\/h2>\n\n\n\n<p>When you genuinely need eval(), the globals and locals parameters are your primary defense mechanism.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import re\n\ndef safe_math_eval(expression):\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Step 1: Validate input characters\n\n&nbsp;&nbsp;&nbsp;&nbsp;pattern = r'^&#91;0-9\\s\\+\\-\\*\\\/\\%\\(\\)\\.\\*\\*]+$'\n\n&nbsp;&nbsp;&nbsp;&nbsp;if not re.match(pattern, expression):\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(\"Expression contains invalid characters\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Step 2: Restrict namespace completely\n\n&nbsp;&nbsp;&nbsp;&nbsp;safe_globals = {\"__builtins__\": {}}&nbsp; &nbsp; # disable ALL built-ins\n\n&nbsp;&nbsp;&nbsp;&nbsp;safe_locals = {}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # no variables allowed\n\n&nbsp;&nbsp;&nbsp;&nbsp;# Step 3: Evaluate in the restricted environment\n\n&nbsp;&nbsp;&nbsp;&nbsp;try:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = eval(expression, safe_globals, safe_locals)\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result\n\n&nbsp;&nbsp;&nbsp;&nbsp;except ZeroDivisionError:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(\"Division by zero\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;except Exception as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(f\"Invalid expression: {e}\")\n\n# Safe use\n\nprint(safe_math_eval(\"2 + 3 * 4\")) &nbsp; &nbsp; &nbsp; # 14\n\nprint(safe_math_eval(\"100 \/ 5\"))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 20.0\n\nprint(safe_math_eval(\"2 ** 8\")) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 256\n\n# Blocked dangerous inputs\n\ntry:\n\n&nbsp;&nbsp;&nbsp;&nbsp;safe_math_eval(\"__import__('os').system('ls')\")\n\nexcept ValueError as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;print(f\"Blocked: {e}\")<\/code><\/pre>\n\n\n\n<ol>\n<li>By setting __builtins__ to None, we disable all built-in functions, and then only safe functions are allowed in safe_locals, thereby reducing risks.&nbsp;<\/li>\n\n\n\n<li>For expression calculation, you can use the ast.literal_eval() function in the ast module. ast.literal_eval() can only parse Python&#8217;s literal structures such as strings, numbers, tuples, lists, dictionaries, and cannot execute operations such as function calls and variable references, so it is safer.<\/li>\n\n\n\n<li>When the input is untrusted, there is no completely effective way to avoid the security risks associated with eval(). However, you can minimize your risk by restricting the execution environment of eval().<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Safe Alternatives to eval()<\/strong><\/h2>\n\n\n\n<p>Before reaching for eval(), consider these safer alternatives that cover most common use cases:<\/p>\n\n\n\n<p><strong>ast.literal_eval()<\/strong> is the best alternative when you need to parse Python data structures like lists, dictionaries, tuples, and strings from user input:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import ast\n\n# Safe: only parses literal Python structures\n\ndata = ast.literal_eval(\"&#91;1, 2, 3, {'key': 'value'}]\")\n\nprint(data) &nbsp; &nbsp; &nbsp; &nbsp; # &#91;1, 2, 3, {'key': 'value'}]\n\nprint(type(data)) &nbsp; # &lt;class 'list'&gt;\n\n# Also safe for numbers, strings, booleans\n\nnumber = ast.literal_eval(\"42\")\n\nprint(number) &nbsp; &nbsp; &nbsp; # 42\n\n# Cannot execute arbitrary code - this raises ValueError\n\ntry:\n\n&nbsp;&nbsp;&nbsp;&nbsp;ast.literal_eval(\"__import__('os').system('ls')\")\n\nexcept ValueError as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;print(f\"Safely blocked: {e}\")<\/code><\/pre>\n\n\n\n<p><strong>json.loads()<\/strong> is the right choice when parsing data that comes in <a href=\"https:\/\/www.guvi.in\/blog\/complete-guide-on-how-to-open-a-json-file\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSON <\/a>format from APIs or configuration files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import json\n\njson_data = '{\"name\": \"Alice\", \"age\": 30, \"scores\": &#91;95, 87, 92]}'\n\ndata = json.loads(json_data)\n\nprint(data&#91;\"name\"]) &nbsp; &nbsp; # Alice\n\nprint(data&#91;\"scores\"]) &nbsp; # &#91;95, 87, 92]<\/code><\/pre>\n\n\n\n<p><strong>The operator module<\/strong> is useful for dynamic mathematical operations without the security risk:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import operator\n\nops = {\n\n&nbsp;&nbsp;&nbsp;&nbsp;'+': operator.add,\n\n&nbsp;&nbsp;&nbsp;&nbsp;'-': operator.sub,\n\n&nbsp;&nbsp;&nbsp;&nbsp;'*': operator.mul,\n\n&nbsp;&nbsp;&nbsp;&nbsp;'\/': operator.truediv\n\n}\n\ndef calculate(a, op_symbol, b):\n\n&nbsp;&nbsp;&nbsp;&nbsp;if op_symbol not in ops:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(f\"Unsupported operation: {op_symbol}\")\n\n&nbsp;&nbsp;&nbsp;&nbsp;return ops&#91;op_symbol](a, b)\n\nprint(calculate(10, '+', 5))&nbsp; &nbsp; # 15\n\nprint(calculate(10, '*', 3))&nbsp; &nbsp; # 30<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>eval() vs exec(): Understanding the Difference<\/strong><\/h2>\n\n\n\n<p>A common source of confusion for beginners is the difference between eval() and exec(). They are related but serve different purposes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># eval() evaluates EXPRESSIONS and RETURNS a value\n\nresult = eval(\"3 + 4\")\n\nprint(result)&nbsp; &nbsp; # 7\n\n# exec() executes STATEMENTS but returns None\n\nexec(\"x = 3 + 4\")\n\nprint(x) &nbsp; &nbsp; &nbsp; &nbsp; # 7&nbsp; (x was set in the current namespace)\n\nprint(exec(\"3 + 4\"))&nbsp; # None\n\n# eval() raises SyntaxError for statements\n\ntry:\n\n&nbsp;&nbsp;&nbsp;&nbsp;eval(\"x = 10\")&nbsp; &nbsp; # Assignment is a statement, not expression\n\nexcept SyntaxError as e:\n\n&nbsp;&nbsp;&nbsp;&nbsp;print(f\"SyntaxError: {e}\")<\/code><\/pre>\n\n\n\n<p>Use eval() when you need the result of an expression. Use exec() when you want to execute statements that have side effects like variable assignments or function definitions. Both carry similar security risks and both should be used with great caution.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Quick Reference: When to Use and When to Avoid eval()<\/strong><\/h2>\n\n\n\n<ol>\n<li><strong>Use eval()<\/strong> when the input comes from a trusted source like your own configuration files or internal program logic, when you need to evaluate mathematical expressions in a tightly controlled sandbox, when the use case genuinely cannot be solved with ast.literal_eval(), json.loads(), or the operator module, and when performance optimization requires dynamic expression evaluation in a controlled environment.<\/li>\n\n\n\n<li><strong>Avoid eval() <\/strong>when the expression string comes from user input, web requests, <a href=\"https:\/\/www.guvi.in\/blog\/api-response-structure-best-practices\/\" target=\"_blank\" rel=\"noreferrer noopener\">API <\/a>responses, or any external source. Avoid it when ast.literal_eval() would solve the same problem more safely. Avoid it in production code handling sensitive data or operations.<\/li>\n<\/ol>\n\n\n\n<p><em>Now that you understand how Python\u2019s eval() dynamically evaluates string expressions and where it\u2019s safe (or unsafe) to use it, ready to go deeper into Python and build real, secure programs? <\/em><a href=\"https:\/\/www.guvi.in\/courses\/programming\/?utm_source=blog&amp;utm_medium=hyperlink&amp;utm_campaign=eval-python\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Start learning Python with HCL GUVI\u2019s Programming Course <\/em><\/a><em>and master core concepts, functions, and best practices for writing clean, safe code<\/em><\/p>\n\n\n\n<p><strong>Wrapping Up<\/strong><\/p>\n\n\n\n<p>eval() is one of Python&#8217;s most powerful and most misunderstood built-in functions. The ability to treat a string as executable code and get a result back is genuinely useful in the right contexts, from dynamic calculators and configuration-driven systems to developer tools that need runtime code generation. Understanding how its three parameters work, especially how globals and locals create an execution sandbox, gives you the control you need to use it responsibly.<\/p>\n\n\n\n<p>The security risks are real and should never be dismissed. A<strong>ny eval() call that processes input from an untrusted source is a potential vulnerability. The rule is simple: reach for ast.literal_eval() or json.loads() first, use the operator module for dynamic math, and only turn to eval() when you have exhausted safer alternatives and can guarantee the expression comes from a trusted, controlled source with a properly restricted namespace.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>FAQ<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1780897378483\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>1. When should I use eval()?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Only for trusted, controlled expressions you cannot handle with safer tools \u2014 e.g., internal config expressions, developer tools, or controlled runtime code generation where you can tightly restrict the namespace.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1780897384976\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">2.<strong> How can I make eval() safer?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Validate the string (allow only safe characters\/patterns), pass restricted globals\/locals (set &#8220;<em>_builtins<\/em>_&#8221; to {} or None), and expose only the specific functions\/values needed. Even then, treat it cautiously.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1780897397555\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>3. What\u2019s a safe alternative to eval() for parsing data?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Use ast.literal_eval() for Python literals (numbers, strings, lists, dicts, tuples). Use json.loads() for JSON data and the operator module or a small expression parser for controlled math.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1780897402789\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>4. Can eval() execute statements like assignments or loops?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. eval() only evaluates expressions. Use exec() to run statements (but exec() returns None and is similarly risky).<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1780897420940\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>5. What happens if I call eval() without globals\/locals?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>eval() runs in the current scope and can access your variables and builtins, which is convenient but increases the attack surface if the input is untrusted.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Python\u2019s eval() lets you turn a string into executable code at runtime. eval (&#8220;3 + 4&#8221;) returns 7, showcasing the language\u2019s expressiveness and flexibility. This dynamic evaluation powers simple calculators, configurable expression-driven systems, and lightweight code generation tools without building a custom parser.&nbsp; Use it carefully, though: executing untrusted strings is a serious security risk [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":115223,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[717],"tags":[],"views":"35","authorinfo":{"name":"Vishalini Devarajan","url":"https:\/\/www.guvi.in\/blog\/author\/vishalini\/"},"thumbnailURL":"https:\/\/www.guvi.in\/blog\/wp-content\/uploads\/2026\/05\/python-eval-explained-and-how-it-works-300x115.webp","_links":{"self":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/113038"}],"collection":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/comments?post=113038"}],"version-history":[{"count":6,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/113038\/revisions"}],"predecessor-version":[{"id":119375,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/113038\/revisions\/119375"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media\/115223"}],"wp:attachment":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media?parent=113038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/categories?post=113038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/tags?post=113038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}