Show code of exception occurred when call exec on python
python 에서 exec
함수를 통해 임의의 코드를 수행시킬때, 예외가 발생했다면, 예외가 발생한 부분을 정확히 알고 싶을때 어떻게 할 수 있을까요@.@?
다음과 같이 traceback 을 서식화 하여 출력할때, File "<string>", line 4
처럼 출력되어서 정확한 위치를 알기 귀찮습니다.
import traceback
codes = []
codes.append("""\
print("hello", end='')
print(" ", end='')
print("world")
""")
codes.append("""\
def add(a, b):
return a + b
print('2 + 3 => {}'.format(add(2, 3)))
r = addd(4, 5)
print('4 + 5 => {}'.format(r))
""")
try:
for code in codes:
exec(code)
except Exception as _:
print(traceback.format_exc())
위 코드를 실행한 결과는 다음과 같습니다.
hello world
2 + 3 => 5
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
File "<string>", line 5, in <module>
NameError: name 'addd' is not defined
코드가 짧을 경우, 문제가 발생한 부분을 짚어내기 어렵지 않지만, 수십, 수백라인의 코드를 exec
호출을 통해서 실행중 예외가 발생한 경우 문제가 발생한 코드를 찾아내는것은 쉽지 않을 수 있습니다.
이를 쉽게 처리하기 위해서, code
에서 문제가 발생한 라인의 코드를 추출하면 됩니다.
말을 길게 했지만, 단순히 다음과 같이 처리하면 됩니다. :P
import traceback
codes = []
codes.append("""\
print("hello", end='')
print(" ", end='')
print("world")
""")
codes.append("""\
def add(a, b):
return a + b
print('2 + 3 => {}'.format(add(2, 3)))
r = addd(4, 5)
print('4 + 5 => {}'.format(r))
""")
execode = None
try:
for code in codes:
execode = code # save current running code
exec(code)
except Exception as e:
tbf = traceback.format_exc()
print(tbf)
if 'File \"<string>\"' in tbf: # find `File "<string>"`
found = re.search(r'File "<string>", line (\d+)', tbf) # search exception occurred line
if found is not None:
lineno = int(found.group(1))
print(
"<string> => {{\n" +
"\n".join(['{:03d} {}'.format(i+1, x) for (i, x) in enumerate(execode.splitlines()) if i >= (lineno-2) and i < (lineno+1)]) +
"\n}}"
)
위와 같이 하면, 다음처럼 예외가 발생한 라인 근처의 코드를 포함하여 출력합니다. :)
hello world
2 + 3 => 5
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "<string>", line 5, in <module>
NameError: name 'addd' is not defined
<string> => {{
004 print('2 + 3 => {}'.format(add(2, 3)))
005 r = addd(4, 5)
006 print('4 + 5 => {}'.format(r))
}}
쓸만한진 모르겠지만, 나름 나쁘진 않지 않아영@.@?