如何在python中创建代码对象? [英] How to create a code object in python?

查看:82
本文介绍了如何在python中创建代码对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个具有类型type.CodeType()的新代码对象。

几乎没有关于此的文档,并且现有的文档说不虚心。

告诉我我需要什么,并给我一些有关传递给type.CodeType的每个参数的信息。

可能发布一个示例。

I'd like to create a new code object with the function types.CodeType() .
There is almost no documentation about this and the existing one says "not for faint of heart"
Tell me what i need and give me some information about each argument passed to types.CodeType ,
possibly posting an example.

注意

在正常情况下,您只需要内置函数compile()

仅在需要时才使用types.CodeType()创建无法通过编写常规源代码而获得的新指令,并且需要直接访问字节码。

Note:
In normal use cases you will just need the builtin function compile()
You should use types.CodeType() only if you want to create new instructions that couldn't be obtained writing normal source code and that require direct access to bytecode.

推荐答案

––– ––––––––

免责声明

此答案中的文档不是官方的,可能不正确。

–––––––––––
Disclaimer :
Documentation in this answer is not official and may be incorrect.

此答案仅对python 3.x版有效。

This answer is valid only for python version 3.x

–––––––– -

–––––––––––

要创建代码对象,您必须传递给函数CodeType() e以下参数:

In order to create a code object you have to pass to the function CodeType() the following arguments:

CodeType(
        argcount,             #   integer
        kwonlyargcount,       #   integer
        nlocals,              #   integer
        stacksize,            #   integer
        flags,                #   integer
        codestring,           #   bytes
        consts,               #   tuple
        names,                #   tuple
        varnames,             #   tuple
        filename,             #   string
        name,                 #   string
        firstlineno,          #   integer
        lnotab,               #   bytes
        freevars,             #   tuple
        cellvars              #   tuple
        )

现在,我将尝试解释每个参数的含义。

Now i will try to explain what is the meaning of each argument.

argcount

要传递给函数的参数数量(不包括* args和** kwargs) 。

argcount
Number of arguments to be passed to the function (*args and **kwargs are not included).

kwonlyargcount

仅关键字参数

nlocals

局部变量的数量,

即所有变量和参数(* args和全局变量除外。

nlocals
Number of local variables ,
namely all variables and parameters(*args and **kwargs included) except global names.

stacksize
代码所需的堆栈量(虚拟机堆栈) ,

如果您想了解其工作原理,请参见官方文档

标志

位图说明了有关代码对象的内容:

1 –>代码已优化

2 –> newlocals:有一个新的本地命名空间(例如一个函数)

4 –>该代码接受任意数量的位置参数(使用* args)

8 –>代码接受任意数量的关键字参数(使用* kwargs)

32 –>代码为生成器

flags
A bitmap that says something about the code object:
1 –> code was optimized
2 –> newlocals: there is a new local namespace(for example a function)
4 –> the code accepts an arbitrary number of positional arguments (*args is used)
8 –> the code accepts an arbitrary number of keyworded arguments (*kwargs is used)
32 –> the code is a generator

othes标志在较旧的python版本中使用或被激活为说出从__ 将来 __

othes flags are used in older python versions or are activated to say what is imported from __ future __

代码字符串

表示字节的序列字节码说明

如果您想更好地理解,请参见文档(与上面相同)

const

一个元组,其中包含字节码使用的文字(例如,预先计算出的数字,元组和字符串)

consts
A tuple containing literals used by the bytecode (for example pre-computed numbers, tuples,and strings)

名称

包含由bytecode

此名称是全局变量,函数和类,还是从对象加载的属性

names
A tuple containing names used by the bytecode
this names are global variables, functions and classes or also attributes loaded from objects

varnames

一个包含字节码使用的本地名称的元组(首先是参数,然后是局部变量)

varnames
A tuple containing local names used by the bytecode (arguments first, then local variables)

文件名


它可以是您想要的任何内容,您可以我可以随便撒谎。 ;)

filename
It is the filename from which the code was compiled.
It can be whatever you want,you are free to lie about this. ;)

名称

它给出了函数的名称。
也可以是您想要的任何内容,但要小心:

这是回溯中显示的名称,如果名称不清楚,则回溯可能不清楚,

只是想想lambda会令人讨厌。

name
It gives the name of the function. Also this can be whatever you want,but be careful:
this is the name shown in the traceback,if the name is unclear,the traceback could be unclear,
just think about how lambdas can be annoying.

firstlineno

函数的第一行(用于调试目的)如果您已编译源代码)

firstlineno
The first line of the function (for debug purpose if you compiled source code)

lnotab

字节映射,将字节码偏移量与行号相关联。

(我认为这也是出于调试目的,关于此目的的文档很少)

lnotab
A mapping of bytes that correlates bytecode offsets to line numbers.
(i think also this is for debug purpose,there is few documentation about this)

freevars

包含自由变量名称的元组。

自由变量是在定义代码对象的命名空间中声明的变量,
在声明嵌套函数时使用;

在模块级别不会发生这种情况,因为在这种情况下,自由变量也是全局变量。

freevars
A tuple containing the names of free variables.
Free variables are variables declared in the namespace where the code object was defined, they are used when nested functions are declared;
this doesn't happen at module level because in that case free variables are also global variables.

cellvars

包含名称的元组嵌套函数引用的局部变量。

cellvars
A tuple containing names of local variables referenced by nested functions.

––––––––––––

示例

以下示例应阐明上面所说的含义。

––––––––––––
Examples :
following examples should clarify the meaning of what has been said above.

注意:在完成的代码对象中,上述属性具有 co _ 前缀,

函数将其可执行主体存储在 __ code __ 属性

Note: in finished code objects attributes mentioned above have the co_ prefix,
and a function stores its executable body in the __code__ attribute

–––––––––––

第一个示例

––––––––––––
1st Example

def F(a,b):
    global c
    k=a*c
    w=10
    p=(1,"two",3)

print(F.__code__.co_argcount)
print(F.__code__.co_nlocals , F.__code__.co_varnames)
print(F.__code__.co_stacksize)
print(F.__code__.co_flags)
print(F.__code__.co_names)
print(F.__code__.co_consts)

输出:

2
5 ('a', 'b', 'k', 'w', 'p')
3
67
('c' ,)
(None, 10, 1, 'two'. 3, (1, 'two', 3))




  1. 有两个参数传递给此函数( a, b)

  1. there are two arguments passed to this function ("a","b")

此函数具有两个参数( a, b)和三个局部变量( k, w, p)

this function has two parameters("a","b") and three local variables("k","w","p")

反汇编函数字节码,我们得到以下代码:

disassembling the function bytecode we obtain this:

3         0 LOAD_FAST                0 (a)             #stack:  ["a"] 
          3 LOAD_GLOBAL              0 (c)             #stack:  ["a","c"]
          6 BINARY_MULTIPLY                            #stack:  [result of a*c]
          7 STORE_FAST               2 (k)             #stack:  []

4        10 LOAD_CONST               1 (10)            #stack:  [10]
         13 STORE_FAST               3 (w)             #stack:  []

5        16 LOAD_CONST               5 ((1, 'two', 3)) #stack:  [(1,"two",3)]
         19 STORE_FAST               4 (p)             #stack:  []
         22 LOAD_CONST               0 (None)          #stack:  [None]
         25 RETURN_VALUE                               #stack:  []

您可以注意到智利执行该函数的过程中,我们从来没有超过三个元素堆栈(在这种情况下,元组以其长度计)

as you can notice chile executing the function we never have more than three elements in the stack (tuple counts as its lenght in this case)

标志的值是 dec 67 = bin 1000011 = bin 1000000 +10 +1 = dec 64 +2 +1,因此我们了解到

flag's value is dec 67 = bin 1000011 = bin 1000000 +10 +1 = dec 64 +2 +1 ,so we understand that


  • 对代码进行了优化(因为大多数自动生成的代码已被优化)

  • 在执行函数字节码本地名称空间更改时

  • 64吗?其实我不知道它是什么意思

该函数中唯一使用的全局名称是 c ,它存储在co_names

the only global name that is used in the function is "c" , it is stored in co_names

我们使用的每个显式文字都存储在co_consts中:

every explicit literal we use is stored in co_consts:


  • 该函数的返回值都不是

  • 我们将数字10明确分配给w

  • 我们明确分配(1, 'two',3)到p

  • 如果元组是常量,则该元组的每个元素都是常量,因此1, two,3是常量<​​/ li>
  • None is the return value of the function
  • we explicitly assign the number 10 to w
  • we explicitly assign (1, 'two', 3) to p
  • if the tuple is a constant each element of that tuple is a constant,so 1,"two",3 are constants

–––––––––––

第二个示例

––––––––––––
2nd example

ModuleVar="hi"

def F():
    FunctionVar=106
    UnusedVar=ModuleVar

    def G():
        return (FunctionVar,ModuleVar)

    print(G.__code__.co_freevars)
    print(G.__code__.co_names)

F()
print(F.__code__.co_cellvars)
print(F.__code__.co_freevars)
print(F.__code__.co_names)

输出:

('FunctionVar',)
('ModuleVar',)
('FunctionVar',)
()
('print', '__code__', 'co_freevars', 'co_names', 'ModuleVar')

输出的含义是:

在执行F时打印第一行和第二行,因此它们显示了G代码的co_freevars和co_name:

FunctionVar位于F函数的命名空间中,其中G已创建,

ModuleVar而是模块变量,因此被视为全局变量。

first and second line are printed when F is executed,so they show co_freevars and co_names of G code:
"FunctionVar" is in the namespace of F function,where G was created,
"ModuleVar" instead is a module variable,so it is considered as global.

以下三行涉及F代码的co_cellvars,co_freevars和co_names属性:

在嵌套函数G中引用了 FunctionVar,因此标记为cellvar,

ModuleVar在创建F的名称空间中,但它是模块变量,

因此未标记为freevar,但它是在全局名称中可以找到。

内置函数print也标记在names中,并且在F中使用了所有属性的名称。

following three lines are about co_cellvars,co_freevars and co_names attributes of F code:
"FunctionVar" is referenced in the G nested function ,so it is marked as a cellvar,
"ModuleVar" is in the namespace where F was created,but it is a module variable,
so it is not marked as freevar,but it is found in global names.
also the builtin function print is marked in names , and all the names of attributes used in F.

- ––––––––

第三个​​示例

––––––––––––
3rd example

这是工作代码对象的初始化,

这是没有用的,但是您可以使用此功能执行所有操作。

This is a working code object initialization,
this is unuseful but you can do everything you want with this function.

MyCode= CodeType(
        0,
        0,
        0,
        3,
        64,
        bytes([101, 0, 0,    #Load print function
               101, 1, 0,    #Load name 'a'
               101, 2, 0,    #Load name 'b'
               23,           #Take first two stack elements and store their sum
               131, 1, 0,    #Call first element in the stack with one positional argument
               1,            #Pop top of stack
               101, 0, 0,    #Load print function
               101, 1, 0,    #Load name 'a'
               101, 2, 0,    #Load name 'b'
               20,           #Take first two stack elements and store their product
               131, 1, 0,    #Call first element in the stack with one positional argument
               1,            #Pop top of stack
               100, 0, 0,    #Load constant None
               83]),         #Return top of stack
        (None,),
        ('print', 'a', 'b'),
        (),
        'PersonalCodeObject',
        'MyCode',
        1,
        bytes([14,1]),
        (),
        () )

a=2
b=3
exec(MyCode) # code prints the sum and the product of "a" and "b"

输出:

5
6

这篇关于如何在python中创建代码对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆