Using compile
I've come up with a solution using the built-in function compile
, as follows.
Contents of the file main.py
:
with open('test.py') as f:
source_code = f.read()
compiled = compile(
source_code,
filename='test.py', mode='exec', optimize=2)
exec(compiled)
Contents of the file test.py
:
if __debug__:
print('Debug ON')
else:
print('Debug OFF')
The output from running python main.py
is:
Debug OFF
Possible values for the parameter optimize
:
-1
: use same optimization level as the Python interpreter that is running the function compile
0
: no optimization, and __debug__ == true
1
: like -O
, i.e., removes assert
statements, and __debug__ == false
2
: like -OO
, i.e., removes also docstrings.
Don't know if it's the best option, just sharing if can be useful fo others.
Using subprocess.run
The subprocess
-based approach is still more concise, and can be made portable by using sys.executable
:
import subprocess
import sys
if not sys.executable:
raise RuntimeError(sys.executable)
proc = subprocess.run(
[sys.executable, '-OO', 'test.py'],
capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(proc.returncode)
The above code calls the function subprocess.run
.
The check for the value of the variable sys.executable
is motivated by the documentation of CPython:
If Python is unable to retrieve the real path to its executable, sys.executable
will be an empty string or None
.
The check is implemented with a raise
statement, instead of an assert
statement, in order to check also in cases that the above Python code is itself run with optimization requested from Python, e.g., by using python -O
or python -OO
or the environment variable PYTHONOPTIMIZE
.
When optimization is requested, assert
statements are removed.
Using raise
statements also enables raising an exception other than AssertionError
, in this case RuntimeError
.
For running Python code that is within a function inside the same source file (i.e., inside main.py
, not inside test.py
), the function inspect.getsource
can be used, together with the option -c
of python
.
By the way better answers are welcome!