2012-09-04 3 views
13

파이썬 C API 함수 PyEval_EvalCode 컴파일 된 파이썬 코드를 실행 해 봅시다. 파이썬 코드 블록을 함수의 범위 내에서 실행하는 것처럼 실행하여 전역 상태에 영향을주지 않는 로컬 변수 사전을 갖도록합니다. PyEval_EvalCode 당신이 글로벌 및 로컬 사전을 제공 할 수 있기 때문에C 파이썬 : 컨텍스트 내에서 파이썬 코드 실행

이, 쉽게 할만큼 보인다

PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)

내가 파이썬 변수 이름을 검색하는 방법과 관련이있다로 실행 문제. 내가 PyEval_EvalCode으로 실행하는 것이, 다음 코드를 고려 : 파이썬은 func 내에서 변수 myvar을 찾을 수 없기 때문에

myvar = 300 
def func(): 
    return myvar 

func() 

이 간단한 코드는 실제로 오류가 발생합니다. myvar이 외부 범위의 로컬 사전에 있더라도 Python은이를 내부 범위의 로컬 사전에 복사하지 않습니다. 이유는 다음과 같습니다 :

파이썬이 변수 이름을 찾을 때마다 먼저 locals을 확인한 다음 globals을 확인하고 마지막으로 builtins을 확인합니다. 모듈 범위에서 localsglobals은 SAME 사전 개체입니다. 따라서 모듈 범위에있는 x = 5 문은 locals 사전에 x을 배치합니다. globals 사전입니다. 이제 모듈 범위에서 정의 된 함수 x은 함수 범위 locals 안에있는 x을 찾지 못합니다. Python이 모듈 범위 로컬을 함수 범위 로컬에 복사하지 않기 때문입니다. 그러나 이것은 보통 globals에서 x을 찾을 수 있기 때문에 문제가되지 않습니다.

x = 5 
def foo(): 
    print(x) # This works because 'x' in globals() == True 

파이썬은 내부 스코프 지역 주민에 외부 범위의 지역 주민을 복사 할 것 같다 만에 중첩 기능입니다. (또한 그들이 내부 범위 내에서 필요한 경우에만, 너무 느리게 할 것 같다.)

def foo(): 
    x = 5 
    def bar(): 
     print(x) # Now 'x' in locals() == True 
    bar() 


그래서이 모든 결과가 모듈 범위에서 코드를 실행할 때, 당신이해야한다는 것입니다 전역 사전과 로컬 사전이 같은 객체인지 확인하십시오. 그렇지 않으면 모듈 범위 함수가 모듈 범위 변수에 액세스 할 수 없습니다.

하지만 제 경우에는 전역 사전과 로컬 사전을 같게 지정하지 마십시오. 따라서 파이썬 인터프리터에게 함수 범위에서 코드를 실행 중임을 알리는 방법이 필요합니다. 이것을 할 수있는 방법이 있습니까? PyCompileFlags과 추가 인수 인 PyEval_EvalCodeEx을 보았고이를 수행 할 수있는 방법을 찾을 수 없습니다.

답변

3

파이썬은 실제로 외부 범위의 로컬을 내부 범위의 로컬로 복사하지 않습니다. locals에 대한 설명서는

무료 변수는 함수 블록에서는 호출되지만 클래스 블록에서는 호출되지 않을 때 지역 변수()가 반환합니다.

여기서 "자유"변수는 중첩 된 함수에 의해 폐쇄 된 변수를 나타냅니다. 그것은 중요한 차이입니다. 당신이 함수에 코드를 포장하고, 컴파일 된 객체에서 추출 할 수 있습니다, 그렇지 않으면

code = """ 
myvar = 300 
def func(): 
    return myvar 

func() 
""" 
d = {} 
eval(compile(code, "<str>", "exec"), d, d) 

:

상황에 간단한 수정 globalslocals같은 DICT 개체를 전달하는 단지입니다 :

s = 'def outer():\n ' + '\n '.join(code.strip().split('\n')) 
exec(compile(s, '<str>', 'exec').co_consts[0], {}, {}) 
+0

@ Channel72 위 참조. – ecatmur

관련 문제