¿Cuáles son los argumentos para los tipos.CodeType () llamada de python?

Actualmente estoy tratando de lanzar mi propio código “marshal” para python para poder almacenar el código comstackdo de python en Google App Engine para que sirva los scripts de forma dinámica. Como todos ustedes pueden verificar, “marshal” no es compatible con GAE y “pickle” no puede serializar objetos de código.

Descubrí que puedo construir un objeto de código con types.CodeType() pero espera 12 argumentos.

Por mucho que lo he intentado, no puedo encontrar ninguna documentación sobre esta llamada y realmente necesito construir el objeto de código para poder exec() . Mi pregunta es, ¿alguien sabe cuáles son los parámetros para este types.CodeType() “constructor” types.CodeType() o alguna forma de verlo? He usado la función info() definida aquí, ¡ pero escupe información genérica!

Preguntas frecuentes rápidas:

  • P: ¿Por qué comstackr el código?
  • R: El tiempo de CPU cuesta dinero real en Google App Engine, y cada bit de ciclos de CPU puedo guardar cuentas.
  • P: ¿Por qué no usar “mariscal”?
  • R: Es uno de los módulos no admitidos en Google App Engine .
  • P: ¿Por qué no usar “pickle”?
  • R: Pickle no admite la serialización de objetos de código.

ACTUALIZAR

La infraestructura de Google App Engine no permite la creación de instancias de objetos de código a partir del 7 de julio de 2011, por lo que mi argumento aquí es discutible. Espero que esto se arregle en el futuro en GAE.

Fui y tomé el código encontrado aquí y eliminé la dependencia del módulo “nuevo” en desuso.

 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') 

La función de la API C PyCode_New se documenta (mínimamente) aquí: http://docs.python.org/c-api/code.html – el código fuente C de esta función (Python 2.7) está aquí: 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) 

Sin embargo, en el constructor de Python, los últimos seis argumentos parecen ser intercambiados un poco. Este es el código C que extrae los argumentos transmitidos por 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): # ... 

La pregunta formulada:

¿Cuáles son los parámetros para este tipo.CodeType () “constructor”

De los documentos de python sobre el módulo de inspección :

 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 

Esta publicación de blog tiene una explicación mucho más detallada: http://tech.blog.aknin.name/2010/07/03/pythons-innards-code-objects/

Nota: la publicación del blog habla sobre python 3, mientras que los documentos de python citados anteriormente son python 2.7.

Respondiendo a la pregunta que necesita, en lugar de a la que hizo:

No puede ejecutar un bytecode arbitrario en el entorno de App Engine Python, actualmente. Aunque es posible que pueda acceder al código de bytes o a los objetos de código, no puede cargar uno.

Sin embargo, tiene una alternativa: almacenamiento en caché por instancia. Almacene las claves de un almacén de datos de asignación de dict global (para las entradas de su almacén de datos que almacenan el código de Python) en el objeto de código comstackdo. Si el objeto no existe en el caché, compílelo desde el origen y almacénelo allí. Tendrá que hacer el trabajo de comstackción en cada instancia, pero no tiene que hacerlo en cada solicitud, lo que le ahorrará mucho trabajo.