types.CodeType() python 调用的参数是什么?

发布于 2024-11-18 16:54:22 字数 1031 浏览 2 评论 0原文

我目前正在尝试为 python 推出我自己的“marshal”代码,以便我可以将编译后的 python 代码存储在 Google App Engine 上,以动态方式提供脚本。正如大家可以验证的那样,GAE 不支持“marshal”,并且“pickle”无法序列化代码对象。

我发现我可以使用 types.CodeType() 构造一个代码对象,但它需要 12 个参数。

尽管我已经尝试过,但我找不到有关此调用的任何文档,而且我确实需要构造代码对象,以便我可以 exec() 它。我的问题是,有谁知道这个types.CodeType()“构造函数”的参数是什么,或者有什么方法可以内省它吗?我已经使用了info () 函数在此处定义,但它只输出通用信息!

快速常见问题解答:

  • 问:为什么要编译代码?
  • 答:在 Google App Engine 上,CPU 时间花费了真金白银,而每一点 CPU 周期我都可以节省计数。
  • 问:为什么不使用“元帅”?
  • 答:这是 Google App Engine 中不支持的模块
  • 问:为什么不使用“pickle”?
  • 答:Pickle 不支持代码对象的序列化。

更新

自 2011 年 7 月 7 日起,Google App Engine 基础架构不允许实例化代码对象,因此我的论点毫无意义。希望 GAE 将来能解决这个问题。

I'm currently trying to roll my own "marshal" code for python so i can store compiled python code on Google App Engine to serve scripts on a dynamic way. As you all can verify, "marshal" isn't supported on GAE and "pickle" can't serialize code objects.

I found out i can construct a code object with types.CodeType() but it expects 12 arguments.

As much as i've tried, i can't find any documentation on this call and i really need to construct the code object so i can exec() it. My question is, does anyone know what are the parameters for this types.CodeType() "constructor" or any way to introspect it? i have used the info() function defined here but it spits out just generic info!

Quick FAQ:

  • Q: Why compile the code?
  • A: CPU time costs real money on Google App Engine, and every bit of CPU cycles i can save counts.
  • Q: Why not use "marshal"?
  • A: That's one of the unsupported modules in Google App Engine.
  • Q: Why not use "pickle"?
  • A: Pickle doesn't support serialization of code objects.

UPDATE

Google App Engine infrastructure doesn't allow the instantiation of code objects as of 7th July 2011, so my argument here is moot. Hope this gets fixed in the future on GAE.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷血 2024-11-25 16:54:22

问题问:

此类型的参数是什么。CodeType()“构造函数”

来自有关 inspect 模块的 python 文档< /a>:

co_argcount: number of arguments (not including * or ** args)
co_code: string of raw compiled bytecode
co_consts: tuple of constants used in the bytecode
co_filename: name of file in which this code object was created
co_firstlineno: number of first line in Python source code
co_flags: bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
co_lnotab: encoded mapping of line numbers to bytecode indices
co_name: name with which this code object was defined
co_names: tuple of names of local variables
co_nlocals: number of local variables
co_stacksize: virtual machine stack space required
co_varnames: tuple of names of arguments and local variables

这篇博文有更详细的解释:http://tech.blog.aknin.name/2010/07/03/pythons-innards-code-objects/

注意:博客文章讨论的是 python 3,而引用的 python 文档以上是Python 2.7。

The question asked:

what are the parameters for this types.CodeType() "constructor"

From the python docs about the inspect module:

co_argcount: number of arguments (not including * or ** args)
co_code: string of raw compiled bytecode
co_consts: tuple of constants used in the bytecode
co_filename: name of file in which this code object was created
co_firstlineno: number of first line in Python source code
co_flags: bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
co_lnotab: encoded mapping of line numbers to bytecode indices
co_name: name with which this code object was defined
co_names: tuple of names of local variables
co_nlocals: number of local variables
co_stacksize: virtual machine stack space required
co_varnames: tuple of names of arguments and local variables

This blog post has much more detailed explanation: http://tech.blog.aknin.name/2010/07/03/pythons-innards-code-objects/

Note: the blog post talks about python 3 while the quoted python docs above is python 2.7.

听你说爱我 2024-11-25 16:54:22

C API 函数 PyCode_New 的(最低限度)记录如下: http://docs.python.org /c-api/code.html — 该函数的 C 源代码 (Python 2.7) 位于:http://hg.python.org/cpython/file/b5ac5e25d506/Objects /codeobject.c#l43

PyCodeObject *
PyCode_New(int argcount, int nlocals, int stacksize, int flags,
           PyObject *code, PyObject *consts, PyObject *names,
           PyObject *varnames, PyObject *freevars, PyObject *cellvars,
           PyObject *filename, PyObject *name, int firstlineno,
           PyObject *lnotab)

但是,在 Python 构造函数中,最后六个参数似乎略有交换。这是提取 Python 传入的参数的 C 代码: http ://hg.python.org/cpython/file/b5ac5e25d506/Objects/codeobject.c#l247

if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
                      &argcount, &nlocals, &stacksize, &flags,
                      &code,
                      &PyTuple_Type, &consts,
                      &PyTuple_Type, &names,
                      &PyTuple_Type, &varnames,
                      &filename, &name,
                      &firstlineno, &lnotab,
                      &PyTuple_Type, &freevars,
                      &PyTuple_Type, &cellvars))
    return NULL;

Python化:

def __init__(self, argcount, nlocals, stacksize, flags, code,
                   consts, names, varnames, filename, name, 
                   firstlineno, lnotab, freevars=None, cellvars=None): # ...

The C API function PyCode_New is (minimally) documented here: http://docs.python.org/c-api/code.html ­— the C source code of this function (Python 2.7) is here: http://hg.python.org/cpython/file/b5ac5e25d506/Objects/codeobject.c#l43

PyCodeObject *
PyCode_New(int argcount, int nlocals, int stacksize, int flags,
           PyObject *code, PyObject *consts, PyObject *names,
           PyObject *varnames, PyObject *freevars, PyObject *cellvars,
           PyObject *filename, PyObject *name, int firstlineno,
           PyObject *lnotab)

However, in the Python constructor, the last six arguments appear to be swapped around a little. This is the C code that extracts the arguments passed in by Python: http://hg.python.org/cpython/file/b5ac5e25d506/Objects/codeobject.c#l247

if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
                      &argcount, &nlocals, &stacksize, &flags,
                      &code,
                      &PyTuple_Type, &consts,
                      &PyTuple_Type, &names,
                      &PyTuple_Type, &varnames,
                      &filename, &name,
                      &firstlineno, &lnotab,
                      &PyTuple_Type, &freevars,
                      &PyTuple_Type, &cellvars))
    return NULL;

Pythonized:

def __init__(self, argcount, nlocals, stacksize, flags, code,
                   consts, names, varnames, filename, name, 
                   firstlineno, lnotab, freevars=None, cellvars=None): # ...
天赋异禀 2024-11-25 16:54:22

我去拿了找到的代码 此处 并删除了已弃用的依赖项“新”模块。

import types, copy_reg
def code_ctor(*args):
    # delegate to new.code the construction of a new code object
    return types.CodeType(*args)
def reduce_code(co):
    # a reductor function must return a tuple with two items: first, the
    # constructor function to be called to rebuild the argument object
    # at a future de-serialization time; then, the tuple of arguments
    # that will need to be passed to the constructor function.
    if co.co_freevars or co.co_cellvars:
        raise ValueError, "Sorry, cannot pickle code objects from closures"
    return code_ctor, (co.co_argcount, co.co_nlocals, co.co_stacksize,
        co.co_flags, co.co_code, co.co_consts, co.co_names,
        co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno,
        co.co_lnotab)
# register the reductor to be used for pickling objects of type 'CodeType'
copy_reg.pickle(types.CodeType, reduce_code)
if __name__ == '__main__':
    # example usage of our new ability to pickle code objects
    import cPickle
    # a function (which, inside, has a code object, of course)
    def f(x): print 'Hello,', x
    # serialize the function's code object to a string of bytes
    pickled_code = cPickle.dumps(f.func_code)
    # recover an equal code object from the string of bytes
    recovered_code = cPickle.loads(pickled_code)
    # build a new function around the rebuilt code object
    g = types.FunctionType(recovered_code, globals( ))
    # check what happens when the new function gets called
    g('world')

I went and took the code found here and removed the dependency for the deprecated "new" module.

import types, copy_reg
def code_ctor(*args):
    # delegate to new.code the construction of a new code object
    return types.CodeType(*args)
def reduce_code(co):
    # a reductor function must return a tuple with two items: first, the
    # constructor function to be called to rebuild the argument object
    # at a future de-serialization time; then, the tuple of arguments
    # that will need to be passed to the constructor function.
    if co.co_freevars or co.co_cellvars:
        raise ValueError, "Sorry, cannot pickle code objects from closures"
    return code_ctor, (co.co_argcount, co.co_nlocals, co.co_stacksize,
        co.co_flags, co.co_code, co.co_consts, co.co_names,
        co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno,
        co.co_lnotab)
# register the reductor to be used for pickling objects of type 'CodeType'
copy_reg.pickle(types.CodeType, reduce_code)
if __name__ == '__main__':
    # example usage of our new ability to pickle code objects
    import cPickle
    # a function (which, inside, has a code object, of course)
    def f(x): print 'Hello,', x
    # serialize the function's code object to a string of bytes
    pickled_code = cPickle.dumps(f.func_code)
    # recover an equal code object from the string of bytes
    recovered_code = cPickle.loads(pickled_code)
    # build a new function around the rebuilt code object
    g = types.FunctionType(recovered_code, globals( ))
    # check what happens when the new function gets called
    g('world')
离线来电— 2024-11-25 16:54:22

回答您需要回答的问题,而不是您提出的问题:

目前,您无法在 App Engine Python 环境中执行任意字节码。尽管您也许能够访问字节码或代码对象,但无法加载它们。

不过,您还有另一种选择:按实例缓存。将全局字典映射数据存储键(用于存储 Python 代码的数据存储条目)存储到已编译的代码对象。如果该对象不存在于缓存中,则从源代码编译它并将其存储在那里。您必须在每个实例上执行编译工作,但不必在每个请求上执行此操作,这将为您节省大量工作。

Answering the question you need answered rather than the one you asked:

You can't execute arbitrary bytecode in the App Engine Python environment, currently. Although you may be able to access the bytecode or code objects, you can't load one.

You have an alternative, however: per-instance caching. Store a global dict mapping datastore keys (for your datastore entries that store the Python code) to the compiled code object. If the object doesn't exist in the cache, compile it from source and store it there. You'll have to do the compilation work on each instance, but you don't have to do it on each request, which should save you a lot of work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文