Python/ビルトインがビルトインされるまで
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Pythonを読む]]
#contents
*はじめに [#t38e4dc8]
それではオブジェクト表現について見ていきます。まずはオブ...
2 0 LOAD_BUILD_CLASS
2 LOAD_CONST 0 (<code object...
4 LOAD_CONST 1 ('Foo')
6 MAKE_FUNCTION 0
8 LOAD_CONST 1 ('Foo')
10 CALL_FUNCTION 2
12 STORE_NAME 0 (Foo)
特徴的なのは、クラス定義のコードオブジェクトを関数オブジ...
13のCALL_FUNCTION時点でのスタックは以下のようになっていま...
'Foo'
Fooクラス定義の関数オブジェクト
__build_class__の関数オブジェクト
*Python関数のC実装 [#v9f847d3]
というわけで__build_class__関数の実装であるbuiltin___buil...
・・・の前に、何故これを見ればいいという話になるかを説明...
*builtins [#j0b5bf2c]
まずはLOAD_BUILD_CLASSの処理コードについて見てみましょう...
#code(C){{
TARGET(LOAD_BUILD_CLASS) {
_Py_IDENTIFIER(__build_class__);
PyObject *bc;
if (PyDict_CheckExact(f->f_builtins)) {
bc = _PyDict_GetItemId(f->f_builtins, &Py...
if (bc == NULL) {
PyErr_SetString(PyExc_NameError,
"__build_class__ not ...
goto error;
}
Py_INCREF(bc);
}
else {
PyObject *build_class_str = _PyUnicode_Fr...
if (build_class_str == NULL)
goto error;
bc = PyObject_GetItem(f->f_builtins, buil...
if (bc == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyE...
PyErr_SetString(PyExc_NameError,
"__build_class__ ...
goto error;
}
}
PUSH(bc);
DISPATCH();
}
}}
分岐しています。結局やっていることは同じようですが普通は...
fはPyFrameObjectです。
*PyFrame_New (Objects/frameobject.c) [#t2769619]
PyFrameObjectを作っているのはPyFrame_Newです。以前に見た...
#code(C){{
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, Py...
PyObject *locals)
{
PyFrameObject *back = tstate->frame;
PyFrameObject *f;
PyObject *builtins;
Py_ssize_t i;
if (back == NULL || back->f_globals != globals) {
builtins = _PyDict_GetItemId(globals, &PyId___bui...
if (builtins) {
if (PyModule_Check(builtins)) {
builtins = PyModule_GetDict(builtins);
assert(builtins != NULL);
}
}
if (builtins == NULL) {
// 省略
}
else
Py_INCREF(builtins);
}
else {
// 省略
}
// frameの確保。省略
f->f_stacktop = f->f_valuestack;
f->f_builtins = builtins;
Py_XINCREF(back);
f->f_back = back;
// 変数の設定などなど。省略
}
}}
globalsから__builtins__モジュールを取り出してPyFrameObjec...
次はglobalsがどこで設定されているかをたどる必要はあります...
*PyRun_InteractiveOneObject (Python/pythonrun.c) [#uf2090...
globalsはceval.cにあるPy_EvalCodeに渡されるわけですが大元...
#code(C){{
int
PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, ...
{
PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name;
mod_ty mod;
PyArena *arena;
char *ps1 = "", *ps2 = "", *enc = NULL;
int errcode = 0;
_Py_IDENTIFIER(encoding);
_Py_IDENTIFIER(__main__);
mod_name = _PyUnicode_FromId(&PyId___main__); /* borr...
// 途中省略
mod = PyParser_ASTFromFileObject(fp, filename, enc,
Py_single_input, ps1...
flags, &errcode, are...
Py_XDECREF(v);
Py_XDECREF(w);
Py_XDECREF(oenc);
m = PyImport_AddModuleObject(mod_name);
d = PyModule_GetDict(m);
v = run_mod(mod, filename, d, d, flags, arena);
PyArena_Free(arena);
Py_DECREF(v);
flush_io();
return 0;
}
}}
PyImport_AddModuleObjectはPython/import.cに書かれています...
*_Py_InitializeEx_Private (Python/pylifecycle.c) [#lf07e3...
__main__が定義されているところを求めてさらにプログラムの...
Py_Initializeの実体は_Py_InitializeEx_Privateで名前の通り...
#code(C){{
void
_Py_InitializeEx_Private(int install_sigs, int install_im...
{
PyInterpreterState *interp;
PyThreadState *tstate;
PyObject *bimod, *sysmod, *pstderr;
extern void _Py_ReadyTypes(void);
// 省略
interp = PyInterpreterState_New();
tstate = PyThreadState_New(interp);
(void) PyThreadState_Swap(tstate);
_Py_ReadyTypes();
// 省略
bimod = _PyBuiltin_Init();
_PyImport_FixupBuiltin(bimod, "builtins");
interp->builtins = PyModule_GetDict(bimod);
Py_INCREF(interp->builtins);
// 省略
initmain(interp); /* Module __main__ */
// 省略
}
}}
builtinsとか__main__が関係ありそうなのはこれぐらいになり...
**_PyBuiltin_Init (Python/bltmodule.c) [#r000b487]
builtinsのオブジェクトを作ってるらしい_PyBuiltin_Initを見...
#code(C){{
PyObject *
_PyBuiltin_Init(void)
{
PyObject *mod, *dict, *debug;
mod = PyModule_Create(&builtinsmodule);
dict = PyModule_GetDict(mod);
#define SETBUILTIN(NAME, OBJECT) \
if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJE...
return NULL;
SETBUILTIN("None", Py_None);
SETBUILTIN("Ellipsis", Py_Ellipsis);
// 中略
SETBUILTIN("type", &PyType_Type);
SETBUILTIN("zip", &PyZip_Type);
debug = PyBool_FromLong(Py_OptimizeFlag == 0);
if (PyDict_SetItemString(dict, "__debug__", debug) < ...
Py_DECREF(debug);
return NULL;
}
Py_DECREF(debug);
return mod;
#undef SETBUILTIN
}
}}
builtinsmoduleは_PyBuiltin_Initのすぐ上にあります。なお、...
#code(C){{
static struct PyModuleDef builtinsmodule = {
PyModuleDef_HEAD_INIT,
"builtins",
builtin_doc,
-1, /* multiple "initialization" just copies the modu...
builtin_methods,
NULL,
NULL,
NULL,
NULL
};
}}
builtin_methodsはさらにその上。PyMethodDefの定義はInclude...
#code(C){{
static PyMethodDef builtin_methods[] = {
{"__build_class__", (PyCFunction)builtin___build_clas...
METH_VARARGS | METH_KEYWORDS, build_class_doc},
{"__import__", (PyCFunction)builtin___import__, ...
// 中略
{"vars", builtin_vars, METH_VARARGS,...
{NULL, NULL},
};
}}
おっ、__build_class__がありました、ってとこですがまずはbu...
***PyModule_Create2 (Objects/moduleobject.c) [#h2ba25b8]
モジュールを作成するためのPyModule_Createは、Include/mods...
#code(C){{
PyObject *
PyModule_Create2(struct PyModuleDef* module, int module_a...
{
const char* name;
PyModuleObject *m;
PyInterpreterState *interp = PyThreadState_Get()->int...
if (!PyModuleDef_Init(module))
return NULL;
name = module->m_name;
if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
return NULL;
if (module->m_methods != NULL) {
if (PyModule_AddFunctions((PyObject *) m, module-...
Py_DECREF(m);
return NULL;
}
}
if (module->m_doc != NULL) {
if (PyModule_SetDocString((PyObject *) m, module-...
Py_DECREF(m);
return NULL;
}
}
m->md_def = module;
return (PyObject*)m;
}
}}
PyModule_New、およびそこから呼ばれているPyModule_NewObject
#code(C){{
PyObject *
PyModule_New(const char *name)
{
PyObject *nameobj, *module;
nameobj = PyUnicode_FromString(name);
if (nameobj == NULL)
return NULL;
module = PyModule_NewObject(nameobj);
Py_DECREF(nameobj);
return module;
}
PyObject *
PyModule_NewObject(PyObject *name)
{
PyModuleObject *m;
m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
m->md_def = NULL;
m->md_state = NULL;
m->md_weaklist = NULL;
m->md_name = NULL;
m->md_dict = PyDict_New();
if (module_init_dict(m, m->md_dict, name, NULL) != 0)
goto fail;
PyObject_GC_Track(m);
return (PyObject *)m;
fail:
Py_DECREF(m);
return NULL;
}
}}
dictが出てきました。なおたびたび出てきているPyModule_GetD...
後は、dictに関数が登録されているのを確認できればOKです。...
#code(C){{
int
PyModule_AddFunctions(PyObject *m, PyMethodDef *functions)
{
int res;
PyObject *name = PyModule_GetNameObject(m);
if (name == NULL) {
return -1;
}
res = _add_methods_to_object(m, name, functions);
Py_DECREF(name);
return res;
}
static int
_add_methods_to_object(PyObject *module, PyObject *name, ...
{
PyObject *func;
PyMethodDef *fdef;
for (fdef = functions; fdef->ml_name != NULL; fdef++) {
func = PyCFunction_NewEx(fdef, (PyObject*)module,...
if (PyObject_SetAttrString(module, fdef->ml_name,...
Py_DECREF(func);
return -1;
}
Py_DECREF(func);
}
return 0;
}
}}
C言語の関数に対応するPyCFunctionObjectが作られ、それがモ...
+PyObject_SetAttrString (Objects/object.c)
+PyObject_SetAttr (Objects/object.c)
+PyObject_GenericSetAttr (Objects/object.c)
+_PyObject_GenericSetAttrWithDict (Objects/object.c)
++_PyObject_GetDictPtr (Objects/object.c)
+_PyObjectDict_SetItem (Objects/dictobject.c)
+PyDict_SetItem (Objects/dictobject.c)
**initmain (Python/pylifecycle.c) [#e66b2674]
pylifecycle.cに戻って、最後に__main__モジュールが設定され...
#code(C){{
initmain(PyInterpreterState *interp)
{
PyObject *m, *d, *loader, *ann_dict;
m = PyImport_AddModule("__main__");
d = PyModule_GetDict(m);
ann_dict = PyDict_New();
Py_DECREF(ann_dict);
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
PyObject *bimod = PyImport_ImportModule("builtins...
if (PyDict_SetItemString(d, "__builtins__", bimod...
Py_FatalError("Failed to initialize __main__....
}
Py_DECREF(bimod);
}
// 省略
}
}}
これで__main__.__builtins__が設定されていることも確認でき...
*おわりに [#t936ed71]
今回はクラスの定義処理を見るに先立ってそもそもPythonの関...
の前にbuiltinsがどうなっているのかを見てきました。タイト...
ここまでに出てきて、しれっと流している要素があります。そ...
終了行:
[[Pythonを読む]]
#contents
*はじめに [#t38e4dc8]
それではオブジェクト表現について見ていきます。まずはオブ...
2 0 LOAD_BUILD_CLASS
2 LOAD_CONST 0 (<code object...
4 LOAD_CONST 1 ('Foo')
6 MAKE_FUNCTION 0
8 LOAD_CONST 1 ('Foo')
10 CALL_FUNCTION 2
12 STORE_NAME 0 (Foo)
特徴的なのは、クラス定義のコードオブジェクトを関数オブジ...
13のCALL_FUNCTION時点でのスタックは以下のようになっていま...
'Foo'
Fooクラス定義の関数オブジェクト
__build_class__の関数オブジェクト
*Python関数のC実装 [#v9f847d3]
というわけで__build_class__関数の実装であるbuiltin___buil...
・・・の前に、何故これを見ればいいという話になるかを説明...
*builtins [#j0b5bf2c]
まずはLOAD_BUILD_CLASSの処理コードについて見てみましょう...
#code(C){{
TARGET(LOAD_BUILD_CLASS) {
_Py_IDENTIFIER(__build_class__);
PyObject *bc;
if (PyDict_CheckExact(f->f_builtins)) {
bc = _PyDict_GetItemId(f->f_builtins, &Py...
if (bc == NULL) {
PyErr_SetString(PyExc_NameError,
"__build_class__ not ...
goto error;
}
Py_INCREF(bc);
}
else {
PyObject *build_class_str = _PyUnicode_Fr...
if (build_class_str == NULL)
goto error;
bc = PyObject_GetItem(f->f_builtins, buil...
if (bc == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyE...
PyErr_SetString(PyExc_NameError,
"__build_class__ ...
goto error;
}
}
PUSH(bc);
DISPATCH();
}
}}
分岐しています。結局やっていることは同じようですが普通は...
fはPyFrameObjectです。
*PyFrame_New (Objects/frameobject.c) [#t2769619]
PyFrameObjectを作っているのはPyFrame_Newです。以前に見た...
#code(C){{
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, Py...
PyObject *locals)
{
PyFrameObject *back = tstate->frame;
PyFrameObject *f;
PyObject *builtins;
Py_ssize_t i;
if (back == NULL || back->f_globals != globals) {
builtins = _PyDict_GetItemId(globals, &PyId___bui...
if (builtins) {
if (PyModule_Check(builtins)) {
builtins = PyModule_GetDict(builtins);
assert(builtins != NULL);
}
}
if (builtins == NULL) {
// 省略
}
else
Py_INCREF(builtins);
}
else {
// 省略
}
// frameの確保。省略
f->f_stacktop = f->f_valuestack;
f->f_builtins = builtins;
Py_XINCREF(back);
f->f_back = back;
// 変数の設定などなど。省略
}
}}
globalsから__builtins__モジュールを取り出してPyFrameObjec...
次はglobalsがどこで設定されているかをたどる必要はあります...
*PyRun_InteractiveOneObject (Python/pythonrun.c) [#uf2090...
globalsはceval.cにあるPy_EvalCodeに渡されるわけですが大元...
#code(C){{
int
PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, ...
{
PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name;
mod_ty mod;
PyArena *arena;
char *ps1 = "", *ps2 = "", *enc = NULL;
int errcode = 0;
_Py_IDENTIFIER(encoding);
_Py_IDENTIFIER(__main__);
mod_name = _PyUnicode_FromId(&PyId___main__); /* borr...
// 途中省略
mod = PyParser_ASTFromFileObject(fp, filename, enc,
Py_single_input, ps1...
flags, &errcode, are...
Py_XDECREF(v);
Py_XDECREF(w);
Py_XDECREF(oenc);
m = PyImport_AddModuleObject(mod_name);
d = PyModule_GetDict(m);
v = run_mod(mod, filename, d, d, flags, arena);
PyArena_Free(arena);
Py_DECREF(v);
flush_io();
return 0;
}
}}
PyImport_AddModuleObjectはPython/import.cに書かれています...
*_Py_InitializeEx_Private (Python/pylifecycle.c) [#lf07e3...
__main__が定義されているところを求めてさらにプログラムの...
Py_Initializeの実体は_Py_InitializeEx_Privateで名前の通り...
#code(C){{
void
_Py_InitializeEx_Private(int install_sigs, int install_im...
{
PyInterpreterState *interp;
PyThreadState *tstate;
PyObject *bimod, *sysmod, *pstderr;
extern void _Py_ReadyTypes(void);
// 省略
interp = PyInterpreterState_New();
tstate = PyThreadState_New(interp);
(void) PyThreadState_Swap(tstate);
_Py_ReadyTypes();
// 省略
bimod = _PyBuiltin_Init();
_PyImport_FixupBuiltin(bimod, "builtins");
interp->builtins = PyModule_GetDict(bimod);
Py_INCREF(interp->builtins);
// 省略
initmain(interp); /* Module __main__ */
// 省略
}
}}
builtinsとか__main__が関係ありそうなのはこれぐらいになり...
**_PyBuiltin_Init (Python/bltmodule.c) [#r000b487]
builtinsのオブジェクトを作ってるらしい_PyBuiltin_Initを見...
#code(C){{
PyObject *
_PyBuiltin_Init(void)
{
PyObject *mod, *dict, *debug;
mod = PyModule_Create(&builtinsmodule);
dict = PyModule_GetDict(mod);
#define SETBUILTIN(NAME, OBJECT) \
if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJE...
return NULL;
SETBUILTIN("None", Py_None);
SETBUILTIN("Ellipsis", Py_Ellipsis);
// 中略
SETBUILTIN("type", &PyType_Type);
SETBUILTIN("zip", &PyZip_Type);
debug = PyBool_FromLong(Py_OptimizeFlag == 0);
if (PyDict_SetItemString(dict, "__debug__", debug) < ...
Py_DECREF(debug);
return NULL;
}
Py_DECREF(debug);
return mod;
#undef SETBUILTIN
}
}}
builtinsmoduleは_PyBuiltin_Initのすぐ上にあります。なお、...
#code(C){{
static struct PyModuleDef builtinsmodule = {
PyModuleDef_HEAD_INIT,
"builtins",
builtin_doc,
-1, /* multiple "initialization" just copies the modu...
builtin_methods,
NULL,
NULL,
NULL,
NULL
};
}}
builtin_methodsはさらにその上。PyMethodDefの定義はInclude...
#code(C){{
static PyMethodDef builtin_methods[] = {
{"__build_class__", (PyCFunction)builtin___build_clas...
METH_VARARGS | METH_KEYWORDS, build_class_doc},
{"__import__", (PyCFunction)builtin___import__, ...
// 中略
{"vars", builtin_vars, METH_VARARGS,...
{NULL, NULL},
};
}}
おっ、__build_class__がありました、ってとこですがまずはbu...
***PyModule_Create2 (Objects/moduleobject.c) [#h2ba25b8]
モジュールを作成するためのPyModule_Createは、Include/mods...
#code(C){{
PyObject *
PyModule_Create2(struct PyModuleDef* module, int module_a...
{
const char* name;
PyModuleObject *m;
PyInterpreterState *interp = PyThreadState_Get()->int...
if (!PyModuleDef_Init(module))
return NULL;
name = module->m_name;
if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
return NULL;
if (module->m_methods != NULL) {
if (PyModule_AddFunctions((PyObject *) m, module-...
Py_DECREF(m);
return NULL;
}
}
if (module->m_doc != NULL) {
if (PyModule_SetDocString((PyObject *) m, module-...
Py_DECREF(m);
return NULL;
}
}
m->md_def = module;
return (PyObject*)m;
}
}}
PyModule_New、およびそこから呼ばれているPyModule_NewObject
#code(C){{
PyObject *
PyModule_New(const char *name)
{
PyObject *nameobj, *module;
nameobj = PyUnicode_FromString(name);
if (nameobj == NULL)
return NULL;
module = PyModule_NewObject(nameobj);
Py_DECREF(nameobj);
return module;
}
PyObject *
PyModule_NewObject(PyObject *name)
{
PyModuleObject *m;
m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
m->md_def = NULL;
m->md_state = NULL;
m->md_weaklist = NULL;
m->md_name = NULL;
m->md_dict = PyDict_New();
if (module_init_dict(m, m->md_dict, name, NULL) != 0)
goto fail;
PyObject_GC_Track(m);
return (PyObject *)m;
fail:
Py_DECREF(m);
return NULL;
}
}}
dictが出てきました。なおたびたび出てきているPyModule_GetD...
後は、dictに関数が登録されているのを確認できればOKです。...
#code(C){{
int
PyModule_AddFunctions(PyObject *m, PyMethodDef *functions)
{
int res;
PyObject *name = PyModule_GetNameObject(m);
if (name == NULL) {
return -1;
}
res = _add_methods_to_object(m, name, functions);
Py_DECREF(name);
return res;
}
static int
_add_methods_to_object(PyObject *module, PyObject *name, ...
{
PyObject *func;
PyMethodDef *fdef;
for (fdef = functions; fdef->ml_name != NULL; fdef++) {
func = PyCFunction_NewEx(fdef, (PyObject*)module,...
if (PyObject_SetAttrString(module, fdef->ml_name,...
Py_DECREF(func);
return -1;
}
Py_DECREF(func);
}
return 0;
}
}}
C言語の関数に対応するPyCFunctionObjectが作られ、それがモ...
+PyObject_SetAttrString (Objects/object.c)
+PyObject_SetAttr (Objects/object.c)
+PyObject_GenericSetAttr (Objects/object.c)
+_PyObject_GenericSetAttrWithDict (Objects/object.c)
++_PyObject_GetDictPtr (Objects/object.c)
+_PyObjectDict_SetItem (Objects/dictobject.c)
+PyDict_SetItem (Objects/dictobject.c)
**initmain (Python/pylifecycle.c) [#e66b2674]
pylifecycle.cに戻って、最後に__main__モジュールが設定され...
#code(C){{
initmain(PyInterpreterState *interp)
{
PyObject *m, *d, *loader, *ann_dict;
m = PyImport_AddModule("__main__");
d = PyModule_GetDict(m);
ann_dict = PyDict_New();
Py_DECREF(ann_dict);
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
PyObject *bimod = PyImport_ImportModule("builtins...
if (PyDict_SetItemString(d, "__builtins__", bimod...
Py_FatalError("Failed to initialize __main__....
}
Py_DECREF(bimod);
}
// 省略
}
}}
これで__main__.__builtins__が設定されていることも確認でき...
*おわりに [#t936ed71]
今回はクラスの定義処理を見るに先立ってそもそもPythonの関...
の前にbuiltinsがどうなっているのかを見てきました。タイト...
ここまでに出てきて、しれっと流している要素があります。そ...
ページ名: