compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
Compiles source into a code or AST object. The code object can be executed by exec() or eval().
The return value is a code object.
The compilation process converts the source code into underlying bytecode, improving the efficiency of repeated execution.
source: Required, the source code to be compiled, which can be a string, bytes object, or AST object.
filename: Required, the name of the file from which the code is sourced. It should be a string. If the code does not need to be read from a file, recognizable values can be passed (commonly used is ‘<string>’).
mode: Required, the mode for compiling the code. It should be a string.
mode=’exec’, compiles multiple lines of code.
s = """a = 20
b = 25
c = a + b
print(f'{a} + {b} = {c}')"""
d = compile(s, '<string>', 'exec')
print(type(d)) # Output: <class 'code'>
exec(d) # Output: 20 + 25 = 45
mode=’eval’, compiles a single expression and returns the result of the expression.
s = '20+25'
d = compile(s, '<string>', 'eval')
print(type(d)) # Output: <class 'code'>
print(eval(d)) # Output: 45
mode=’single’, compiles a single line of code, printing the result of the expression, similar to an interactive environment.
Multiple statements are separated by semicolons, only the non-None result of the last expression is printed.
s = 'x = 20+25;x*2'
d = compile(s, '<string>', 'single')
print(type(d)) # Output: <class 'code'>
exec(d) # Output: 90
flags: Optional, controls compilation features.
1. __future__ features: Allows enabling future Python features at compile time.
from __future__ import annotations
s = """def demo(name: str) -> str: return f'{name}'
print(demo.__annotations__)"""
f = annotations.compiler_flag
d = compile(s, '<string>', 'exec', flags=f)
exec(d) # Output: {'name': 'str', 'return': 'str'}
2. AST mode: flags=ast.PyCF_ONLY_AST, returns an AST object, the abstract syntax tree.
ast.Expression
import ast
s = '20 + 25'
f = ast.PyCF_ONLY_AST
d = compile(s, '<string>', 'eval', flags=f)
print(type(d)) # Output: <class 'ast.Expression'>
print(ast.unparse(d)) # Output: 20 + 25
c = compile(d, '<ast>', 'eval')
print(eval(c)) # Output: 45
ast.Module
import ast
s = """x = 20 + 25
print(f'20 + 25 = {x}')"""
f = ast.PyCF_ONLY_AST
d = compile(s, '<string>', 'exec', flags=f)
print(type(d)) # Output: <class 'ast.Module'>
c = compile(d, '<ast>', 'exec')
exec(c) # Output: 20 + 25 = 45
ast.Interactive
import ast
s = '20 + 25'
f = ast.PyCF_ONLY_AST
d = compile(s, '<string>', 'single', flags=f)
print(type(d)) # Output: <class 'ast.Interactive'>
print(ast.unparse(d)) # Output: 20 + 25
c = compile(d, '<ast>', 'single')
exec(c) # Output: 45
dont_inherit: Optional, controls feature inheritance, default is False.
dont_inherit=False, inherits all compilation features from the current scope.
dont_inherit=True, only uses the compilation features specified by flags, not those from the scope.
optimize: Optional, the optimization level of the compiler.
optimize=-1, selects the same optimization level as the interpreter’s -O option. Default value.
s = """def func_demo(x): '''Demonstration of compiler optimization level''' assert x > 0, "x must be positive"
if __debug__:
print("__debug__ debugging")
return x * 2"""
d = compile(s, '<string>', 'exec', optimize=-1)
env = {}
exec(d, env)
a = env['func_demo']
# If the parameter is negative, the assert statement will raise an error
print(a.__doc__) # Documentation string, Output: Demonstration of compiler optimization level
b = a(2025) # Output: __debug__ debugging
print(b) # Output: 4050
optimize=0, no optimization, __debug__ is true.
s = """def func_demo(x): '''Demonstration of compiler optimization level''' assert x > 0, "x must be positive"
if __debug__:
print("__debug__ debugging")
return x * 2"""
d = compile(s, '<string>', 'exec', optimize=0)
env = {}
exec(d, env)
a = env['func_demo']
# If the parameter is negative, the assert statement will raise an error
print(a.__doc__) # Documentation string, Output: Demonstration of compiler optimization level
b = a(2025) # Output: __debug__ debugging
print(b) # Output: 4050
optimize=1, removes assertions, __debug__ is false.
s = """def func_demo(x): '''Demonstration of compiler optimization level''' assert x > 0, "x must be positive"
if __debug__:
print("__debug__ debugging")
return x * 2"""
d = compile(s, '<string>', 'exec', optimize=1)
env = {}
exec(d, env)
a = env['func_demo']
# optimize=1, removes __debug__ and removes assert statements, inputting a negative number will not raise an error
print(a.__doc__) # Documentation string, Output: Demonstration of compiler optimization level
b = a(-2025) # __debug__ will not execute
print(b) # Output: -4050
optimize=2, removes assertions, __debug__ is false, removes documentation strings.
s = """def func_demo(x): '''Demonstration of compiler optimization level''' assert x > 0, "x must be positive"
if __debug__:
print("__debug__ debugging")
return x * 2"""
d = compile(s, '<string>', 'exec', optimize=2)
env = {}
exec(d, env)
a = env['func_demo']
# optimize=1, removes documentation strings, removes __debug__ and removes assert statements, inputting a negative number will not raise an error
print(a.__doc__) # Documentation string, Output: None
b = a(-2025) # __debug__ will not execute
print(b) # Output: -4050
Compiling invalid source code raises a SyntaxError exception.
The source code contains null bytes, raising a SyntaxError exception. To avoid the exception, null bytes in the source code need to be handled first.
Null byte is represented as \x00.
Null byte string is represented as b”.
s = "a = 'need\x00 python!'" # Source code containing null byte \x00
try:
d = compile(s, "<string>", "exec")
except SyntaxError as e:
print(f"Null byte raised exception: {e}") # Output: Null byte raised exception: source code string cannot contain null bytes
