본문으로 바로가기

문제

 

전역변수에는 exec() 함수를 이용한 동적 코드실행을 통해 정상적으로 값이 대입되었습니다.

if __name__ == '__main__':
    name = None
    code = 'name = "jvv"'
    exec(code)
    print(name)
jvv

 

함수안에서도 작동하는지 보겠습니다.

지정한 지역변수에 값을 넣고 싶은데 원하는 결과가 나오지 않습니다.

def func():
    name = None
    exec('name = "jvv"')
    print(name)

if __name__ == '__main__':
    func()
None

 

 

방법

 

 

exec(object[, globals[, locals]])

  • object: 문자열 또는 코드 객체

  • globals: 전역 딕셔너리

  • locals: 지역 딕셔너리

def func():
    a = None
    b = None
    print(locals())
    print(globals())

if __name__ == '__main__':
    func()
{'b': None, 'a': None}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001A63C98B048>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'c:/Users/Desktop/exec/ex2.py', '__cached__': None, 'func': <function func at 0x000001A63C852F28>}

 

다음과 같이 딕셔너리를 주면 안에 변수가 추가됩니다.

def func():
    locale_dict = {}
    exec('name = "jvv"', None, locale_dict)
    print(locale_dict)

if __name__ == '__main__':
    func()
{'name': 'jvv'}

 

그런데 다음과 같이 지역변수가 exec() 로 실행시킬 코드안의 변수로 들어가는 경우에는 변수를 인식하지 못하고 있습니다.

def func():
    n1 = 2
    locale_dict = {}
    exec("n2 = n1 + 10", None, locale_dict)
    print(locale_dict)

if __name__ == '__main__':
    func()
NameError: name 'n1' is not defined

 

locals() 를 주면 함수 내에 지역변수들을 인식할 수 있습니다.

def func():
    n1 = 2
    exec("n2 = n1 + 10", None, locals())
    print(locals())

if __name__ == '__main__':
    func()
{'n1': 2, 'n2': 12}

 

globals() 사용하면 전역 딕셔너리로 접근하실 수 있습니다.

def func():
    exec("n = 99", globals())
    print(locals())
    print(globals()['n'])

if __name__ == '__main__':
    func()
{}
99

 

 

주의사항

 

해당 지역변수가 정의되어있으면 다음과 같은 결과가 나옵니다.

def func():
    num = None
    exec("num = 512", None, locals())
    print(num)
    print(locals())

if __name__ == '__main__':
    func()
None
{'num': None}

 

def func():
    num = None
    exec("num = 512", globals())
    print(locals())
    print(globals()['num'])

if __name__ == '__main__':
    func()
{'num': None}
512