통역사 내에서 실행되는 Python 코드에서 Sys._getFrame ()에 의해 반환 된 Python 프레임 개체에 쓸 수 있습니까?

StackOverflow https://stackoverflow.com/questions/626835

문제

apropos의 이 질문, 통역사 내에는 프레임 객체를 검사하기 위해 약간의 비계가 있습니다. sys._getframe(). 프레임 객체는 읽는 것처럼 보이지만, 문서에서 명시 적으로 언급하는 명백한 것을 찾을 수는 없습니다. 누군가이 객체를 쓸 수 있는지 (어떤 방식으로) 읽을 수 있는지 확인할 수 있습니까?

import sys

def foobar():
    xx='foo'
    ff = sys._getframe()
    ff.f_locals['xx'] = 'bar'
    print xx

if __name__ == '__main__':
    foobar()

이것은 인쇄한다 'foo'실행할 때 아래 게시물은 대화식 쉘에서 현재 프레임에서 실행될 때 쓸 수있는 변수를 보여줍니다.

도움이 되었습니까?

해결책

Cpython 소스에서 Objects/frameobject.c:

static PyMemberDef frame_memberlist[] = {
    {"f_back",      T_OBJECT,       OFF(f_back),    RO},
    {"f_code",      T_OBJECT,       OFF(f_code),    RO},
    {"f_builtins",  T_OBJECT,       OFF(f_builtins),RO},
    {"f_globals",   T_OBJECT,       OFF(f_globals), RO},
    {"f_lasti",     T_INT,          OFF(f_lasti),   RO},
    {"f_exc_type",  T_OBJECT,       OFF(f_exc_type)},
    {"f_exc_value", T_OBJECT,       OFF(f_exc_value)},
    {"f_exc_traceback", T_OBJECT,   OFF(f_exc_traceback)},
    {NULL}    /* Sentinel */
};
...
static PyGetSetDef frame_getsetlist[] = {
    {"f_locals",    (getter)frame_getlocals, NULL, NULL},
    {"f_lineno",    (getter)frame_getlineno,
                    (setter)frame_setlineno, NULL},
    {"f_trace",     (getter)frame_gettrace, (setter)frame_settrace, NULL},
    {"f_restricted",(getter)frame_getrestricted,NULL, NULL},
    {0}
};

PyMemberDef, 깃발 RO 또는 READONLY 속성이 읽기 전용임을 의미합니다. 용 PyGetSetDef, 그것이 getter 만 있으면 읽습니다. 이것은 모든 속성을 의미하지만 f_exc_type, f_exc_value, f_exc_traceback 그리고 f_trace 생성 후 읽기 전용입니다. 이것은 문서에서도 언급되어 있습니다 데이터 모델.

속성에 의해 언급 된 객체는 반드시 읽기 전용 일 필요는 없습니다. 당신은 이것을 할 수 있습니다 :

>>> f = sys._getframe()
>>> f.f_locals['foo'] = 3
>>> foo
3
>>>

이것은 통역사에서 작동하지만 함수 내부에서 실패합니다. 실행 엔진은 로컬 변수에 별도의 배열을 사용합니다 (f_fastlocals), 합병 된 f_locals 접근 중이지만 대화는 사실이 아닙니다.

>>> def foo():
...   x = 3
...   f = sys._getframe()
...   print f.f_locals['x']
...   x = 4
...   print f.f_locals['x']
...   d = f.f_locals
...   x = 5
...   print d['x']
...   f.f_locals
...   print d['x']
...
>>> foo()
3
4
4
5
>>>

글로벌 프레임에서 f_local ~을 참고하여 f_globals, 이 트릭은 통역사에서 작동합니다. 수정 f_globals 작동하지만 전체 모듈에 영향을 미칩니다.

다른 팁

코드가 모듈 범위에 있기 때문에 nxc의 f_locals [ 'foo'] 예제는 작동합니다. 이 경우 f_locals는 f_globals이고 f_globals는 수정 가능하고 수정은 모듈에 반영됩니다.

기능 범위 내부에서 Localals () 및 F_Locals는 쓰기가 가능하지만 [변경 사항은 통역사가 사용하는 로컬 변수의 값에 영향을 미치지 않을 수 있습니다]." 1 구현 선택입니다. Cpython에는 로컬 변수에 대한 최적화 된 바이트 코드가 있습니다. Load_fast. 파이썬에서 로컬 변수는 함수가 정의되면 (거의 항상) 알려져 있으며 Cpython은 사전 조회가 아닌 변수 값을 얻기 위해 색인 조회를 사용합니다.

이론적으로 사전 조회는 그 테이블을 프록시 할 수 있지만, 이는 작은 이득을 얻기위한 많은 작업입니다.

"로컬 변수"에 대한 예외는 함수가 exec 문을 사용하고 "Module Import *"의 더 이상 사용되지 않은 경우입니다. 생성 된 바이트 코드는 이러한 경우에 따라 다르고 느립니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top