Top-Level Components¶
A Python program isn't one thing — it can be entered in several different ways, each with slightly different rules.
Complete Programs¶
A complete Python program is a text file (usually .py) fed to the interpreter. The file is executed as a module in a fresh __main__ namespace:
The standard guard pattern:
The if __name__ == "__main__": check ensures main() only runs when the script is executed directly — not when the file is imported as a module by something else.
File Input¶
When Python reads a file, it parses the whole thing at once into an AST (Abstract Syntax Tree), then compiles and executes it. This is different from languages that interpret line by line.
You can compile and exec files manually:
Interactive Input¶
In the REPL, each line (or complete statement) is compiled and executed immediately. The result of expressions is displayed:
The REPL assigns the last expression result to the special variable _:
Expression Input¶
eval() evaluates a single expression from a string:
result = eval("2 + 2 * 3")
print(result) # 8
# With custom namespace
ns = {"x": 10, "y": 20}
print(eval("x + y", ns)) # 30
exec() executes arbitrary code (statements and expressions) from a string:
code = """
def greet(name):
return f"Hello, {name}!"
result = greet("World")
"""
ns = {}
exec(code, ns)
print(ns["result"]) # Hello, World!
Never eval() or exec() untrusted input
Both can execute arbitrary code. eval("__import__('os').system('rm -rf /')") is a real attack. Always use safe parsing (like ast.literal_eval() for data) instead.
ast.literal_eval() — Safe Expression Parsing¶
For parsing Python literals (strings, numbers, tuples, lists, dicts, booleans, None) from strings safely:
import ast
# Safe: only parses literals
data = ast.literal_eval('{"key": [1, 2, 3], "flag": True}')
print(data) # {'key': [1, 2, 3], 'flag': True}
# Raises ValueError for non-literals:
ast.literal_eval("__import__('os')") # ValueError
The __main__ Module¶
Python has a built-in __main__ module — it's the environment where top-level code runs. You can import it:
The python -m module invocation runs a module's __main__.py:
python -m http.server 8000 # runs http/server/__main__.py
python -m venv myenv # runs venv/__main__.py
python -m pytest # runs pytest/__main__.py
This is the correct way to ship command-line tools inside a package.