I have a following code:
code = """
print("foo")
if True:
return
print("bar")
"""
exec(code)
print('This should still be executed')
If I run it I get:
Traceback (most recent call last):
File "untitled.py", line 10, in <module>
exec(code)
File "<string>", line 5
SyntaxError: 'return' outside function
How to force exec
stop without errors? Probably I should replace return
with something? Also I want the interpreter work after exec
call.
Here, just do something like this:
class ExecInterrupt(Exception):
pass
def Exec(source, globals=None, locals=None):
try:
exec(source, globals, locals)
except ExecInterrupt:
pass
Exec("""
print("foo")
if True:
raise ExecInterrupt
print("bar")
""")
print('This should still be executed')
If your worry is readability, functions are your first line of defense.
This will work, return only works from within a defined function:
code = """
print("foo")
if not True:
print("bar")
"""
exec(code)
print('This should still be executed')
but if you want to use return, you must do something like:
code = """
def func():
print("foo")
if True:
return
print("bar")
func()
"""
exec(code)
print('This should still be executed')
There is no built-in mechanism that allows you to abort execution of an exec
call. The closest thing we have is sys.exit()
, but that exits the whole program, not just the exec
. Fortunately, this can be worked around with a minor amount of exception handling boilerplate:
my_code = """
import sys
print("foo")
if True:
sys.exit()
print("bar")
"""
try:
exec(my_code)
except SystemExit:
pass
print('This is still executed')
# output:
# foo
# This is still executed
Just for fun, here's another way:
def breakable_exec(code):
exec('for _ in [0]:' + '\n'.join(" " + line for line in code.splitlines()))
code = """
print("foo")
if True:
break
print("bar")
"""
breakable_exec(code)
# => foo