본문 바로가기
Python

파이썬 문자열을 평가하는 eval() 함수의 개념과 활용!

by 산코디 2024. 5. 24.

파이썬의 내장 함수인 eval() 함수는 문자열로 된 파이썬 코드를 실행시켜주는 함수다. 함수 이름의 evalevaluate에서 유래되었으며, 단어의 의미 그대로 “평가하다”, “계산하다”의 의미를 내포하고 있어, 말 그대로 코드를 평가할 때 이 함수를 사용할 수 있다. 보통 연산이나 함수 호출 등의 문자열 코드를 실행시키고자 할 때 사용할 수 있다. 사용법과 개념은 간단하기 때문에 하나씩 살펴보도록 하자.




eval() 함수의 개념

eval() 함수는 파이썬에서 문자열로 표현된 파이썬 표현식을 실행하고 그 결과를 반환하는 함수다. eval() 함수는 동적으로 코드를 실행할 수 있는 기능을 제공하기 때문에, 다양한 상황에서 유용하게 사용될 수 있지만, 그만큼 매우 주의해서 사용해야 한다.


문자열 평가
eval() 함수는 문자열로 된 파이썬 코드를 실행하고 그 결과를 반환하는 함수다.

표현식 실행
eval() 함수는 수식, 변수 참조, 함수 호출 등 다양한 파이썬 표현식을 평가할 수 있다.

동적 코드 실행
eval() 함수는 런타임에 동적으로 코드를 실행할 수 있게 한다. 유연한 코드 작성이 가능하지만, 보안 위험도 내포되어 있다.

제한된 환경설정
globals와 locals 인자를 사용하여 eval() 함수가 접근할 수 있는 변수와 함수의 범위를 제한할 수 있다. 이를 통해 실행 환경을 제어하고 잠재적인 보안 문제를 해결할 수 있다.

성능
eval() 함수는 실행 시점에 문자열을 파싱하고 평가하므로, 성능상 부담이 될 수 있다. 반복적인 작업에서능 성능 저하를 유발할 수 있다.



eval() 함수의 문법

eval() 함수는 기본적으로 세 개의 매개변수를 받아 처리한다. 기본 문법을 통해 각 매개변수가 하는일을 살펴보자.

기본 문법

eval(expression, globals=None, locals=None)


expression
평가할 파이썬 표현식을 포함하는 문자열이며, 필수 매개변수다. 수식, 변수 참조, 함수 호출 등의 파이썬 표현식을 포함할 수 있으며, 문자열로 전달해야 한다.

globals
표현식을 평가할 때 사용할 전역 네임 스페이스를 지정한다. 선택적 매개변수이며, dict 타입이어야 한다. 전역변수와 함수를 포함할 수 있다.

locals
표현식을 평가할 때 사용할 지역 네임 스페이스를 지정한다.
globals와 동일하게 선택적 매개변수이며, dict 타입이어야 한다.


위와 같이 eval() 함수는 각각의 매개변수를 통해 코드를 평가하고, globals와 locals의 설정을 통해 코드의 평가 범위와 안전성을 제어하는 데 중요한 역할을 한다.




eval() 함수의 활용
eval() 함수는 다양한 상황과 데이터 유형에 대해 평가 처리할 수 있으먀, 평가 범위 또한 제한이 가능하다. 간단한 예제를 통해서 어떻게 처리되는지 알아보자.


리스트와 딕셔너리

result = eval("[1, 2, 3, 4]")
print(result)  
# 출력: [1, 2, 3, 4]

result = eval("{'key': 'value'}")
print(result)  
# 출력: {'key': 'value'}

위의 코드와 같이 리스트나 딕셔너리로 작성된 문자열 코드를 평가할 때 eval() 함수를 활용할 수 있다. 만약 리스트나 딕셔너리 구조에서 오타가 있거나 조금 다른 부분이 있다면 eval 처리는 되지않고 syntaxError가 발생하게 된다.


수헉 연산

expression = "2 + 3 * (7 - 2)"
result = eval(expression)
print(result)  
# Output: 17

앞서 설명한 바와 같이 수학 연산으로 구성된 문자열의 경우에도 eval() 함수를 활용하여 평가하고 결과를 추출할 수 있다.


함수

def add(x, y):
    return x + y

expression = "add(10, 20)"
result = eval(expression)
print(result)  
# Output: 30

위의 코드는 함수를 호출할 수 있는 문자열을 eval() 함수를 통해 실행하는 예제 코드다. add() 함수에 매개변수를 포함하여 문자열로 세팅한 후 eval() 함수에 전달하면 함수 실향 결과가 반환된다.


동적 함수

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

greet('World')
"""

result = eval(code)
print(result)  
# Output: Hello, World!

위의 코드는 문자열 자체에 함수의 선언과 호출이 포함되어 있다. 이와 같은 경우에도 eval() 함수를 사용하여 실행후 결과를 반환할 수 있다. 이와 같이 동적인 코드를 입력받아 실행하는 경우는 코드의 평가 범위를 제한하는 것이 좋다. 그렇지 않으면 시스템상의 안전성이 문제될 수 있다.


globals

x = 10  # 전역 변수

def example_using_globals():
    result = eval('x + 5', {'x': x})
    return result

print(example_using_globals())  
# 출력: 15

위의 코드는 globals 매개변수를 활용하는 예제다. globals 매개변수로 사용할 값은 전역에 선언되어 있는 x = 10이며, 이 변수를 매개변수로 전달하여 해당 변수만 eval() 함수 내에서 사용하게 된다. 이렇게 한다면 eval 처리되는 코드상에서 사용되는 변수의 제한을 둘 수 있어 안전상에 유리할 수 있다.


locals

def example_using_locals():
    y = 7  # 지역 변수
    result = eval('y * 2', {}, {'y': y})
    return result

print(example_using_locals())  
# 출력: 14

위의 코드는 locals 매개변수를 사용하는 예제다. globals와는 범위가 다르며, 해당 매개변수를 사용하고자 한다면, globals 매개변수를 빈 딕셔너리라도 세팅을 하고 locals를 넘겨주어야 한다.
locals는 globals와는 조금 다르게 이름의 의미와 같이 지역 변수만 넘길 수 있다. 만약 y = 7 이라는 변수가 전역에 선언되어 있다면 해당 변수는 찾을 수 없어 예기치 못한 이슈가 발생할 수 있다. 그러므로 locals로 변수를 넘겨야 할 때에는 반드시 해당 변수가 지역 변수인지 확인해야 한다.


이렇게 정리한 바와 같이 eval() 함수는 다양한 상황에서 활용이 가능하다. 보안이 중요한 환경이라면 반드시 globals와 locals 매개변수를 활용하여 범위를 제한해주는 것도 좋을 것 같다.




eval() 함수와 exec() 함수 비교

eval() 함수와 유사한 기능을 제공하는 exec() 함수가 있는데, 두 함수 모두 파이썬에서 문자열로 표현된 코드를 실행하는 데 사용된다. 그러나 두 함수는 사용 목적과 동작 방식에 차이가 있으므로 다른점을 비교해보고 상황에 맞게 선택하는 것이 좋다.


용도

eval()
eval() 함수는 주어진 문자열을 파이썬 표현식으로 간주하고 실행한 후 그 결과값을 반환한다. 주로 단일 표현식을 계산할 때 사용한다.
exec()
exec() 함수는 주어진 문자열을 파이썬 문장으로 간주하고 실행한다. 주로 여러 줄의 코드 블록을 실행하거나, 파일을 실행할 때 사용한다.

반환

eval()
eval() 함수는 실행 결과를 반환한다.
exec()
exec() 함수는 반환값이 없기 때문에 실행 결과가 없다.


보안

eval()
eval() 함수는 사용자로부터의 입력이나 외부 데이터를 사용할 때 보안 문제를 주의해야 한다. 사용자가 악의적인 코드를 실행할 수 있는 보안 취약점이 있을 수 있다.
exec()
exec() 함수 역시 보안 취약점이 있으나, 일반적으로 eval() 함수보다는 보안 위험이 적다.

활용

eval()
eval() 함수는 주로 수식을 계산하거나, 동적으로 생성된 코드를 실행하는 데 사용된다.
exec()
exec() 함수는 파일을 실행하거나, 동적으로 생성된 코드 블록을 실행하는 데 사용된다.


eval() 함수는 반환값이 있는 반면에 exec() 함수는 반환값이 없다는 것을 알 수 있고, 이로 인해 사용 목적이 다르다는 것을 확인할 수 있다. 이러한 차이점을 이해하고 적재적소에 맞게 선택해서 활용하는 것이 중요하다.




마무리

파이썬의 eval() 함수에 대해서 정리해 보았는데, 함수의 기능은 생각보다 강력한 것 같다. 그런데 그 만큼 보안상의 취약점이 크기 때문에 이 함수를 사용한다면 반드시 대상 환경에 대해 사용해도 문제없는지 고려해보고 사용하는게 좋을 것 같다. 그리고 마지막에 함께 알아본 exec() 함수 역시 상황에 맞게 적절히 선택하면 좋을 것 같다.

 

경제 지표 서비스

https://econoflow.co.kr

 

Economy Flow

 

econoflow.co.kr

 

 

반응형