본문 바로가기
코딩취미/Python

문자열을 파이썬 코드로 해석해서 실행하는 함수 : eval(), exec() 비교

by 브링블링 2024. 9. 4.
반응형

문자열을 파이썬 코드로 해석해서 실행하는 함수 : eval(), exec() 비교

문자열을 파이썬 코드로 해석해서 실행하는 함수인 eval()과 exec()는 파이썬의 동적 특성을 극대화하는 강력한 도구입니다. 이 두 함수는 입력받은 문자열을 코드로 변환해 실행하는 기능을 제공하며, 특정 상황에서 유연하고 강력한 기능을 발휘할 수 있습니다. eval()은 주로 단일 표현식을 평가하고 그 결과를 반환하는 데 사용되는 반면, exec()는 전체 코드 블록을 실행할 수 있습니다. 하지만 이와 같은 강력한 기능에는 보안상의 취약점과 성능 저하 문제를 동반할 수 있어, 무분별한 사용은 위험을 초래할 수 있습니다. 이 글에서는 eval()과 exec()의 주요 특징에 대해 비교했습니다.

 

Python의  eval() 함수

eval() 함수는 동적인 언어 해석기 기능을 구현하기 위해 제공되었습니다. 파이썬은 동적인 타입 시스템을 갖추고 있어, 런타임 시점에 코드 실행을 조정할 수 있는 기능이 필요했습니다. 이와 같은 필요성에 따라 eval() 함수가 설계되었습니다. 초기에는 주로 간단한 표현식의 계산을 목적으로 사용되었지만, 현재는 다양한 상황에서 쓰일 수 있는 도구가 되었습니다.

1. 특징과 목적

eval() 함수는 파이썬 내장 함수 중 하나로, 문자열로 표현된 파이썬 표현식을 실행하고, 그 결과를 반환하는 기능을 합니다. eval() 함수는 주어진 문자열을 파이썬 코드로 해석하여 실행하므로, 동적으로 코드를 실행하거나 계산할 수 있습니다.

  • 동적으로 코드 실행: 사용자 입력에 따라 프로그램의 동작을 다르게 하고 싶을 때 사용됩니다.
  • 간단한 계산식이나 표현식을 문자열로 입력받아 실행하고 그 결과를 얻을 때 유용합니다.
# 사용자가 입력한 수식을 계산하는 예제
expression = input("계산식을 입력하세요: ")  # 예: '2 + 3 * (4 - 1)'
result = eval(expression)
print(f"계산 결과: {result}")

2. 장점

  • 유연성: 코드를 동적으로 생성하고 실행할 수 있는 유연성을 제공합니다.
  • 간결성: 간단한 문자열 표현식을 직접 실행할 수 있어 코드가 간결해집니다.
# 간단한 수식을 평가하여 결과를 반환하는 예제
expression = "10 * 5 + 3"
result = eval(expression)
print(f"결과: {result}")  # 결과: 53

3. 단점

  • 보안 문제: 외부에서 입력받은 문자열을 eval()로 실행하면, 악의적인 코드가 실행될 수 있는 위험이 있습니다.
  • 디버깅 어려움: 동적으로 생성된 코드는 디버깅이 어렵고, 유지보수가 복잡해질 수 있습니다.
  • 성능 문제: eval()을 사용하는 경우, 코드 실행 시간이 늘어나거나 성능이 저하될 수 있습니다.
# 보안 문제가 발생할 수 있는 예제
user_input = "import os; os.system('rm -rf /')"  # 악의적인 코드
# eval(user_input)  # 이 코드를 실행하면 시스템에 매우 위험합니다!

4. 한계점

  • 안전성 부족: 사용자 입력을 그대로 실행하기 때문에 보안적으로 매우 위험할 수 있습니다.
  • 복잡한 구조: eval()은 복잡한 구문이나 제어 구조를 처리하는 데 적합하지 않으며, 예기치 않은 동작을 초래할 수 있습니다.
  • 환경 제약: eval()은 기본적으로 현재의 전역 및 지역 네임스페이스에서 코드를 실행하기 때문에, 환경에 따라 동작이 달라질 수 있습니다.
# 복잡한 제어 구조가 포함된 문자열을 실행하는 예제
complex_code = """
def add(a, b):
    return a + b

result = add(2, 3)
"""
# eval(complex_code)  # eval은 이처럼 복잡한 코드 블록을 처리하지 못합니다.
반응형

Python의 exec() 함수

exec() 함수는 eval()과 마찬가지로 파이썬의 동적인 특성을 활용하기 위해 설계되었습니다.  과거에 스크립트 실행이나 동적 클래스 및 함수 정의가 필요한 환경에서 주로 사용되었습니다.

1. 특징과 목적

exec()는 파이썬 내장 함수로, 문자열로 표현된 파이썬 코드를 실행하는 데 사용됩니다. 다른 함수들과 달리, exec()는 단순한 표현식뿐만 아니라 전체 파이썬 코드 블록(함수 정의, 클래스 정의, 조건문, 반복문 등)을 실행할 수 있습니다. exec() 함수의 주 목적은 동적으로 코드 블록을 실행하는 것입니다. 이는 프로그램이 런타임 중에 새로운 코드(함수, 클래스 등)를 정의하거나 실행해야 하는 경우에 유용합니다.

  • 구문: exec(object[, globals[, locals]])
    • object: 실행할 코드, 주로 문자열 또는 컴파일된 코드 객체.
    • globals, locals: 코드를 실행할 때 사용할 전역 및 지역 네임스페이스를 지정하는 선택적 매개변수.

( 목적: 런타임에 새로운 코드를 동적으로 생성하고 실행하는 경우)

code = """
def greet(name):
    return f"Hello, {name}!"

greeting = greet('Python')
print(greeting)
"""
exec(code)

2. 장점

  • 유연성: 런타임 중에 동적으로 코드 블록을 작성하고 실행할 수 있습니다. 이로 인해 유연한 프로그램 작성이 가능합니다.
  • 전체 코드 실행: eval()과 달리, 단순한 표현식 외에도 함수 정의, 클래스 정의, 반복문, 조건문 같은 구문을 실행할 수 있습니다.
# 동적으로 변수를 선언하고 값 할당
code = """
x = 10
y = 20
z = x + y
"""
exec(code)
print(z)  # 출력: 30

4. 단점

  • 보안 문제: 외부 입력으로 전달된 코드를 검증 없이 실행하면, 악의적인 코드 실행의 위험이 있습니다.
  • 디버깅 어려움: 동적으로 실행된 코드는 디버깅이 어렵고, 코드의 흐름을 추적하는 데 어려움을 겪을 수 있습니다.
  • 성능 문제: 동적으로 코드를 실행하기 때문에 정적 코드에 비해 성능이 저하될 수 있습니다.
user_input = "import os; os.system('rm -rf /')"  # 매우 위험한 코드!
exec(user_input)  # 실행 시 시스템에 치명적인 피해를 줄 수 있음

5. 한계점

  • 보안성 부족: 외부 입력을 그대로 실행할 경우 보안 취약점이 발생할 수 있습니다.
  • 코드 가독성 문제: 코드가 동적으로 생성 및 실행되므로, 코드의 흐름을 파악하기 어려울 수 있습니다.
  • 복잡한 코드 실행 제한: 복잡한 코드를 동적으로 실행하려는 경우 오류가 발생할 수 있으며, 일부 파이썬 구문은 제대로 처리되지 않을 수 있습니다.
# 복잡한 예외 처리를 포함한 코드를 동적으로 실행할 때 발생하는 문제
code = """
try:
    x = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero")
finally:
    print("Execution finished")
"""
exec(code)  # 정상적으로 동작하지만, 복잡한 코드에서 예외 처리는 더욱 어려워질 수 있음

참고 사이트

  1. Python 공식 문서:
반응형