Каковы аргументы для типов.CodeType() в Python вызов?
в настоящее время я пытаюсь свернуть свой собственный код "Маршала" для python, чтобы я мог хранить скомпилированный код python в Google App Engine для обслуживания скриптов динамическим способом. Как вы все можете убедиться," маршал "не поддерживается в GAE, а" рассол " не может сериализовать объекты кода.
я узнал, что могу построить объект кода с types.CodeType()
но он ожидает, 12 аргументов.
сколько я ни пытался, я не могу найти никакой документации по этому вызову, и мне действительно нужно построить объект кода так что я могу exec()
его. Мой вопрос:кто-нибудь знает, какие параметры для этого types.CodeType()
"конструктор" или любой способ, чтобы проверить это? я использовал определена здесь но он выплевывает только общая информация!
быстрый FAQ:
- Q: зачем компилировать код?
- A: время процессора стоит реальных денег на Google App Engine, и каждый бит циклов процессора я могу сохранить подсчеты.
- Q: почему бы не использовать "маршал"?
- A: это один из неподдерживаемые модули в Google App Engine.
- Q: почему не использовать "рассол"?
- A: рассол не поддерживает сериализацию объектов кода.
обновление
инфраструктура Google App Engine не позволяет создавать экземпляры объектов кода по состоянию на 7 июля 2011 года, поэтому мой аргумент здесь спорный. Надеюсь, это будет исправлено в будущем на GAE.
4 ответов
Я пошел и снял код здесь и удалил зависимость для устаревшего" нового " модуля.
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')
функция API c 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 последние шесть аргументов, похоже, немного меняются местами. Это код C, который извлекает аргументы, переданные 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): # ...
на вопрос:
каковы параметры для этих типов.CodeType() "конструктор"
из документов python о модуль проверить:
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.
отвечая на вопрос, который вам нужно ответить, а не тот, который вы задали:
в настоящее время вы не можете выполнять произвольный байт-код в среде Python App Engine. Хотя вы можете получить доступ к байт-коду или объектам кода, Вы не можете его загрузить.
однако у вас есть альтернатива: кэширование для каждого экземпляра. Сохраните ключи хранилища данных global dict mapping datastore (для записей хранилища данных, хранящих код Python) в объект скомпилированного кода. Если объект не существует в кэше скомпилируйте его из исходного кода и сохраните там. Вам придется выполнять компиляцию для каждого экземпляра, но вам не нужно делать это по каждому запросу, что сэкономит вам много работы.