목차
코드 객체 데이터 구조
CodeObject 상세 분석
Flags 필드 상세 분석
freevars & cellvars
stacksize
백엔드 개발 파이썬 튜토리얼 Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

May 10, 2023 pm 05:46 PM
python

코드 객체 데이터 구조

typedef struct {
    PyObject_HEAD
    int co_argcount;		/* #arguments, except *args */
    int co_kwonlyargcount;	/* #keyword only arguments */
    int co_nlocals;		/* #local variables */
    int co_stacksize;		/* #entries needed for evaluation stack */
    int co_flags;		/* CO_..., see below */
    PyObject *co_code;		/* instruction opcodes */
    PyObject *co_consts;	/* list (constants used) */
    PyObject *co_names;		/* list of strings (names used) */
    PyObject *co_varnames;	/* tuple of strings (local variable names) */
    PyObject *co_freevars;	/* tuple of strings (free variable names) */
    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
    /* The rest aren't used in either hash or comparisons, except for
       co_name (used in both) and co_firstlineno (used only in
       comparisons).  This is done to preserve the name and line number
       for tracebacks and debuggers; otherwise, constant de-duplication
       would collapse identical functions/lambdas defined on different lines.
    */
    unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
    PyObject *co_filename;	/* unicode (where it was loaded from) */
    PyObject *co_name;		/* unicode (name, for reference) */
    int co_firstlineno;		/* first source line number */
    PyObject *co_lnotab;	/* string (encoding addr<->lineno mapping) See
				   Objects/lnotab_notes.txt for details. */
    void *co_zombieframe;     /* for optimization only (see frameobject.c) */
    PyObject *co_weakreflist;   /* to support weakrefs to code objects */
} PyCodeObject;
로그인 후 복사

다음은 코드 객체의 각 필드의 역할입니다.

  • 우선 코드 블록이라는 개념을 이해해야 합니다. , 전체적으로 작은 단위로 실행됩니다. Python의 일반적인 코드 블록에는 함수 본문, 클래스 정의 및 모듈이 포함됩니다.

  • argcount는 코드 블록의 매개변수 수를 나타냅니다. 이 매개변수는 함수 본문 코드 블록에만 유용합니다. 예를 들어 위의 pycdemo.py는 함수가 아닌 모듈입니다. 이므로 이 매개변수의 해당 값은 0입니다.

  • co_code, 이 개체의 특정 콘텐츠는 실제 Python 바이트코드를 저장하는 바이트 시퀀스입니다. 이는 주로 Python 가상 머신 실행에 사용되며 이 기사에서는 자세히 분석하지 않습니다.

  • co_consts, 이 필드는 목록 유형 필드로, 주로 위의 "__main__" 및 100과 같은 일부 문자열 상수와 숫자 상수를 포함합니다.

  • co_filename, 이 필드의 의미는 해당 소스 파일의 파일 이름입니다.

  • co_firstlineno, 이 필드의 의미는 Python 소스 파일의 코드 첫 번째 줄에 나타나는 줄 수입니다. 이 필드는 디버깅할 때 매우 중요합니다.

  • co_flags, 이 필드의 주요 의미는 이 코드 개체의 유형을 식별하는 것입니다. 0x0080은 이 블록이 코루틴임을 나타내고, 0x0010은 이 코드 객체가 중첩되었음을 나타냅니다.

  • co_lnotab, 이 필드의 의미는 주로 각 바이트코드 명령어에 해당하는 소스 코드 줄 수를 계산하는 데 사용됩니다.

  • co_varnames, 이 필드의 주요 의미는 코드 개체에서 로컬로 정의된 이름을 나타내는 것입니다. co_varnames의 반대인

  • co_names는 로컬로 정의되지 않고 코드 개체에 사용되는 이름을 나타냅니다.

  • co_nlocals, 이 필드는 코드 객체에서 로컬로 사용되는 변수의 수를 나타냅니다.

  • co_stackszie, Python 가상 머신은 스택 컴퓨터이므로 이 매개변수의 값은 이 스택에 필요한 최대값을 나타냅니다.

  • co_cellvars, co_freevars, 이 두 필드는 주로 중첩 함수 및 함수 클로저와 관련이 있습니다. 이 필드에 대해서는 후속 기사에서 자세히 설명하겠습니다.

CodeObject 상세 분석

이제 몇 가지 실용적인 예를 사용하여 특정 코드 개체를 분석합니다.

import dis
import binascii
import types

d = 10


def test_co01(c):
    a = 1
    b = 2
    return a + b + c + d
로그인 후 복사

이전 기사에서 함수에 코드 개체 개체가 포함되어 있다고 언급했습니다. test_co01의 코드 개체 개체(전체 코드는 co01 참조)의 출력 결과는 다음과 같습니다.

code
   argcount 1
   nlocals 3
   stacksize 2
   flags 0043 0x43
   code b&#39;6401007d01006402007d02007c01007c0200177c0000177400001753&#39;
  9           0 LOAD_CONST               1 (1)
              3 STORE_FAST               1 (a)

 10           6 LOAD_CONST               2 (2)
              9 STORE_FAST               2 (b)

 11          12 LOAD_FAST                1 (a)
             15 LOAD_FAST                2 (b)
             18 BINARY_ADD
             19 LOAD_FAST                0 (c)
             22 BINARY_ADD
             23 LOAD_GLOBAL              0 (d)
             26 BINARY_ADD
             27 RETURN_VALUE
   consts
      None
      1
      2
   names (&#39;d&#39;,)
   varnames (&#39;c&#39;, &#39;a&#39;, &#39;b&#39;)
   freevars ()
   cellvars ()
   filename &#39;/tmp/pycharm_project_396/co01.py&#39;
   name &#39;test_co01&#39;
   firstlineno 8
   lnotab b&#39;000106010601&#39;
로그인 후 복사
  • 필드 값 argcount는 1과 같습니다. 이는 함수에 하나의 매개변수가 있고 이 함수 test_co01에는 서로 대응하는 매개변수 c가 있음을 나타냅니다.

  • nlocals 필드의 값은 3으로, 총 3개의 함수 로컬 변수 a, b, c가 test_co01 함수에 구현되어 있음을 나타냅니다.

  • 필드 이름은 코드의 co_names에 해당합니다. 이전 정의에 따르면 전역 변수 d는 test_co01 함수에서 사용되지만 함수에서는 정의되지 않습니다.

  • Field varnames는 로컬 정의에 사용되는 변수를 나타냅니다. test_co01 함수에는 a, b, c 세 가지 주요 변수가 있습니다.

  • 필드 파일 이름은 Python 파일의 주소입니다.

  • Field firstlineno는 함수의 첫 번째 줄이 해당 Python 코드의 8번째 줄에 나타남을 나타냅니다.

Flags 필드 상세 분석

분석을 위해 특별히 python3.5의 소스 코드를 사용합니다. cpython 가상 머신의 구체적인 구현은 다음과 같습니다(Include/code.h):

/* Masks for co_flags above */
#define CO_OPTIMIZED	0x0001
#define CO_NEWLOCALS	0x0002
#define CO_VARARGS	0x0004
#define CO_VARKEYWORDS	0x0008
#define CO_NESTED       0x0010
#define CO_GENERATOR    0x0020
/* The CO_NOFREE flag is set if there are no free or cell variables.
   This information is redundant, but it allows a single flag test
   to determine whether there is any extra work to be done when the
   call frame it setup.
*/
#define CO_NOFREE       0x0040

/* The CO_COROUTINE flag is set for coroutine functions (defined with
   ``async def`` keywords) */
#define CO_COROUTINE            0x0080
#define CO_ITERABLE_COROUTINE   0x0100
로그인 후 복사

플래그 필드와 위의 각 매크로 정의는 & 연산을 수행하여 결과가 0보다 크면 해당 조건이 충족되었음을 의미합니다.

위 매크로 정의의 의미는 다음과 같습니다.

  • CO_OPTIMIZED 이 필드는 코드 개체가 최적화되었으며 함수에 의해 로컬로 정의된 변수를 사용함을 나타냅니다.

  • CO_NEWLOCALS, 이 필드의 의미는 이 코드 객체의 코드가 실행될 때 스택 프레임의 f_locals 객체에 대해 dict 객체가 생성된다는 것입니다.

  • CO_VARARGS - 이 코드 객체에 위치 매개변수가 포함되어 있는지 여부를 나타냅니다.

  • CO_VARKEYWORDS - 이 코드 객체에 키워드 매개변수가 포함되어 있는지 여부를 나타냅니다.

  • CO_NESTED, 이 코드 객체가 중첩 함수임을 나타냅니다.

  • CO_GENERATOR은 이 코드 객체가 생성기임을 나타냅니다.

  • CO_COROUTINE은 이 코드 객체가 코루틴 함수임을 나타냅니다.

  • CO_ITERABLE_COROUTINE은 코드 객체가 반복 가능한 코루틴 함수임을 나타냅니다.

  • CO_NOFREE 이는 freevar 및 cellvar가 없음, 즉 함수 폐쇄가 없음을 의미합니다.

이제 이전 함수 test_co01의 플래그를 분석해 보겠습니다. 해당 값은 0x43입니다. 이는 이 함수가 CO_NEWLOCALS, CO_OPTIMIZED 및 CO_NOFREE의 세 가지 특성을 충족한다는 의미입니다.

freevars & cellvars

我们使用下面的函数来对这两个字段进行分析:

def test_co02():
    a = 1
    b = 2

    def g():
        return a + b
    return a + b + g()
로그인 후 복사

上面的函数的信息如下所示(完整代码见co02):

code
   argcount 0
   nlocals 1
   stacksize 3
   flags 0003 0x3
   code
      b&#39;640100890000640200890100870000870100660200640300640400860000&#39;
      b&#39;7d0000880000880100177c00008300001753&#39;
 15           0 LOAD_CONST               1 (1)
              3 STORE_DEREF              0 (a)

 16           6 LOAD_CONST               2 (2)
              9 STORE_DEREF              1 (b)

 18          12 LOAD_CLOSURE             0 (a)
             15 LOAD_CLOSURE             1 (b)
             18 BUILD_TUPLE              2
             21 LOAD_CONST               3 (<code object g at 0x7f133ff496f0, file "/tmp/pycharm_project_396/co01.py", line 18>)
             24 LOAD_CONST               4 (&#39;test_co02.<locals>.g&#39;)
             27 MAKE_CLOSURE             0
             30 STORE_FAST               0 (g)

 20          33 LOAD_DEREF               0 (a)
             36 LOAD_DEREF               1 (b)
             39 BINARY_ADD
             40 LOAD_FAST                0 (g)
             43 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             46 BINARY_ADD
             47 RETURN_VALUE
   consts
      None
      1
      2
      code
         argcount 0
         nlocals 0
         stacksize 2
         flags 0013 0x13
         code b&#39;8800008801001753&#39;
 19           0 LOAD_DEREF               0 (a)
              3 LOAD_DEREF               1 (b)
              6 BINARY_ADD
              7 RETURN_VALUE
         consts
            None
         names ()
         varnames ()
         freevars (&#39;a&#39;, &#39;b&#39;)
         cellvars ()
         filename &#39;/tmp/pycharm_project_396/co01.py&#39;
         name &#39;g&#39;
         firstlineno 18
         lnotab b&#39;0001&#39;
      &#39;test_co02.<locals>.g&#39;
   names ()
   varnames (&#39;g&#39;,)
   freevars ()
   cellvars (&#39;a&#39;, &#39;b&#39;)
   filename &#39;/tmp/pycharm_project_396/co01.py&#39;
   name &#39;test_co02&#39;
   firstlineno 14
   lnotab b&#39;0001060106021502&#39;
로그인 후 복사

从上面的输出我们可以看到的是,函数 test_co02 的 cellvars 为 ('a', 'b'),函数 g 的 freevars 为 ('a', 'b'),cellvars 表示在其他函数当中会使用本地定义的变量,freevars 表示本地会使用其他函数定义的变量。

再来分析一下函数 test_co02 的 flags,他的 flags 等于 0x3 因为有闭包的存在因此 flags 不会存在 CO_NOFREE,也就是少了值 0x0040 。

stacksize

这个字段存储的是在函数在被虚拟机执行的时候所需要的最大的栈空间的大小,这也是一种优化手段,因为在知道所需要的最大的栈空间,所以可以在函数执行的时候直接分配指定大小的空间不需要在函数执行的时候再去重新扩容。

def test_stack():
    a = 1
    b = 2
    return a + b
로그인 후 복사

上面的代码相关字节码等信息如下所示:

code
   argcount 0
   nlocals 2
   stacksize 2
   flags 0043 0x43
   code b&#39;6401007d00006402007d01007c00007c01001753&#39;
   #					  字节码指令		 # 字节码指令参数 # 参数对应的值
 24           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

 25           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

 26          12 LOAD_FAST                0 (a)
             15 LOAD_FAST                1 (b)
             18 BINARY_ADD
             19 RETURN_VALUE
   consts
      None # 下标等于 0 的常量
      1 	 # 下标等于 1 的常量
      2		 # 下标等于 2 的常量
   names ()
   varnames (&#39;a&#39;, &#39;b&#39;)
   freevars ()
   cellvars ()
로그인 후 복사

我们现在来模拟一下执行过程,在模拟之前我们首先来了解一下上面几条字节码的作用:

LOAD_CONST,将常量表当中的下标等于 i 个对象加载到栈当中,对应上面的代码 LOAD_CONST 的参数 i = 1。因此加载测常量等于 1 。因此现在栈空间如下所示:

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

STORE_FAST,将栈顶元素弹出并且保存到 co_varnames 对应的下标当中,根据上面的字节码参数等于 0 ,因此将 1 保存到 co_varnames[0] 对应的对象当中。

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

LOAD_CONST,将下标等于 2 的常量加载进入栈中。

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

STORE_FAST,将栈顶元素弹出,并且保存到 varnames 下标为 1 的对象。

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

LOAD_FAST,是取出 co_varnames 对应下标的数据,并且将其压入栈中。我们直接连续执行两个 LOAD_FAST 之后栈空间的布局如下:

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

BINARY_ADD,这个字节码指令是将栈空间的两个栈顶元素弹出,然后将两个数据进行相加操作,然后将相加得到的结果重新压入栈中。

Python 가상 머신에서 Code 객체의 역할은 무엇입니까?

RETURN_VALUE,将栈顶元素弹出并且作为返回值返回。

从上面的整个执行过程来看整个栈空间使用的最大的空间长度为 2 ,因此 stacksize = 2 。

위 내용은 Python 가상 머신에서 Code 객체의 역할은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

hadidb : 파이썬의 가볍고 수평 확장 가능한 데이터베이스 hadidb : 파이썬의 가볍고 수평 확장 가능한 데이터베이스 Apr 08, 2025 pm 06:12 PM

HADIDB : 가볍고 높은 수준의 확장 가능한 Python 데이터베이스 HadIDB (HADIDB)는 파이썬으로 작성된 경량 데이터베이스이며 확장 수준이 높습니다. PIP 설치를 사용하여 HADIDB 설치 : PIPINSTALLHADIDB 사용자 관리 사용자 만들기 사용자 : createUser () 메소드를 작성하여 새 사용자를 만듭니다. Authentication () 메소드는 사용자의 신원을 인증합니다. Fromhadidb.operationimportuseruser_obj = user ( "admin", "admin") user_obj.

MongoDB 데이터베이스 비밀번호를 보는 Navicat의 방법 MongoDB 데이터베이스 비밀번호를 보는 Navicat의 방법 Apr 08, 2025 pm 09:39 PM

해시 값으로 저장되기 때문에 MongoDB 비밀번호를 Navicat을 통해 직접 보는 것은 불가능합니다. 분실 된 비밀번호 검색 방법 : 1. 비밀번호 재설정; 2. 구성 파일 확인 (해시 값이 포함될 수 있음); 3. 코드를 점검하십시오 (암호 하드 코드 메일).

파이썬 : 기본 응용 프로그램 탐색 파이썬 : 기본 응용 프로그램 탐색 Apr 10, 2025 am 09:41 AM

Python은 웹 개발, 데이터 과학, 기계 학습, 자동화 및 스크립팅 분야에서 널리 사용됩니다. 1) 웹 개발에서 Django 및 Flask 프레임 워크는 개발 프로세스를 단순화합니다. 2) 데이터 과학 및 기계 학습 분야에서 Numpy, Pandas, Scikit-Learn 및 Tensorflow 라이브러리는 강력한 지원을 제공합니다. 3) 자동화 및 스크립팅 측면에서 Python은 자동화 된 테스트 및 시스템 관리와 ​​같은 작업에 적합합니다.

2 시간의 파이썬 계획 : 현실적인 접근 2 시간의 파이썬 계획 : 현실적인 접근 Apr 11, 2025 am 12:04 AM

2 시간 이내에 Python의 기본 프로그래밍 개념과 기술을 배울 수 있습니다. 1. 변수 및 데이터 유형을 배우기, 2. 마스터 제어 흐름 (조건부 명세서 및 루프), 3. 기능의 정의 및 사용을 이해하십시오. 4. 간단한 예제 및 코드 스 니펫을 통해 Python 프로그래밍을 신속하게 시작하십시오.

고로드 애플리케이션의 MySQL 성능을 최적화하는 방법은 무엇입니까? 고로드 애플리케이션의 MySQL 성능을 최적화하는 방법은 무엇입니까? Apr 08, 2025 pm 06:03 PM

MySQL 데이터베이스 성능 최적화 안내서 리소스 집약적 응용 프로그램에서 MySQL 데이터베이스는 중요한 역할을 수행하며 대규모 트랜잭션 관리를 담당합니다. 그러나 응용 프로그램 규모가 확장됨에 따라 데이터베이스 성능 병목 현상은 종종 제약이됩니다. 이 기사는 일련의 효과적인 MySQL 성능 최적화 전략을 탐색하여 응용 프로그램이 고 부하에서 효율적이고 반응이 유지되도록합니다. 실제 사례를 결합하여 인덱싱, 쿼리 최적화, 데이터베이스 설계 및 캐싱과 같은 심층적 인 주요 기술을 설명합니다. 1. 데이터베이스 아키텍처 설계 및 최적화 된 데이터베이스 아키텍처는 MySQL 성능 최적화의 초석입니다. 몇 가지 핵심 원칙은 다음과 같습니다. 올바른 데이터 유형을 선택하고 요구 사항을 충족하는 가장 작은 데이터 유형을 선택하면 저장 공간을 절약 할 수있을뿐만 아니라 데이터 처리 속도를 향상시킬 수 있습니다.

Amazon Athena와 함께 AWS Glue Crawler를 사용하는 방법 Amazon Athena와 함께 AWS Glue Crawler를 사용하는 방법 Apr 09, 2025 pm 03:09 PM

데이터 전문가는 다양한 소스에서 많은 양의 데이터를 처리해야합니다. 이것은 데이터 관리 및 분석에 어려움을 겪을 수 있습니다. 다행히도 AWS Glue와 Amazon Athena의 두 가지 AWS 서비스가 도움이 될 수 있습니다.

MySQL이 SQL 서버에 연결할 수 있습니다 MySQL이 SQL 서버에 연결할 수 있습니다 Apr 08, 2025 pm 05:54 PM

아니요, MySQL은 SQL Server에 직접 연결할 수 없습니다. 그러나 다음 방법을 사용하여 데이터 상호 작용을 구현할 수 있습니다. 미들웨어 사용 : MySQL에서 중간 형식으로 데이터를 내보낸 다음 미들웨어를 통해 SQL Server로 가져옵니다. 데이터베이스 링커 사용 : 비즈니스 도구는 본질적으로 미들웨어를 통해 여전히 구현되는보다 우호적 인 인터페이스와 고급 기능을 제공합니다.

Redis로 서버를 시작하는 방법 Redis로 서버를 시작하는 방법 Apr 10, 2025 pm 08:12 PM

Redis 서버를 시작하는 단계에는 다음이 포함됩니다. 운영 체제에 따라 Redis 설치. Redis-Server (Linux/MacOS) 또는 Redis-Server.exe (Windows)를 통해 Redis 서비스를 시작하십시오. Redis-Cli Ping (Linux/MacOS) 또는 Redis-Cli.exe Ping (Windows) 명령을 사용하여 서비스 상태를 확인하십시오. Redis-Cli, Python 또는 Node.js와 같은 Redis 클라이언트를 사용하여 서버에 액세스하십시오.

See all articles