我正在尝试为python编写自己的“marshal”代码,因此我可以在Google App Engine上存储已编译的python代码,以动态方式提供脚本。大家都可以验证,GAE不支持“marshal”,“pickle”不能序列化代码对象。
我发现我可以使用types.CodeType()
构建一个代码对象,但它需要12个参数。
尽管我已经尝试过,但我找不到关于此调用的任何文档,我真的需要构建代码对象,以便我可以exec()
。我的问题是,有没有人知道这个types.CodeType()
“构造函数”的参数是什么?或者是什么方式来反省它?我使用了info()
定义的函数{{3}但它只吐出通用信息!
快速常见问题解答:
更新
截至2011年7月7日,Google App Engine基础架构不允许实例化代码对象,因此我的论点没有实际意义。希望将来在GAE上得到修复。
答案 0 :(得分:6)
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;
Pythonized:
def __init__(self, argcount, nlocals, stacksize, flags, code,
consts, names, varnames, filename, name,
firstlineno, lnotab, freevars=None, cellvars=None): # ...
答案 1 :(得分:6)
问的问题是:
的python文档此类型的参数是什么.CodeType()“constructor”
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。
答案 2 :(得分:5)
我去找了here找到的代码并删除了已弃用的“新”模块的依赖项。
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')
答案 3 :(得分:2)
回答你需要回答的问题,而不是你问过的问题:
目前,您无法在App Engine Python环境中执行任意字节码。虽然您可以访问字节码或代码对象,但无法加载。
但是,您有另一种选择:每实例缓存。存储全局dict映射数据存储区键(用于存储Python代码的数据存储区条目)到已编译的代码对象。如果缓存中不存在该对象,请从源代码编译它并将其存储在那里。您将不得不对每个实例进行编译工作,但您不必在每个请求上执行此操作,这将为您节省大量工作。