2
3

More than 3 years have passed since last update.

Python/C APIを読む その3(超高水準レイヤ)

Last updated at Posted at 2021-03-26

概要

Pythonの構造を理解する助けとして、C APIのドキュメントを読み砕いていく。

内容

環境

Python 3.9 (CPython)に話を固したいが、必ずしもそうはならない。
tree (コミット; ブランチ)
(↑ githubのリンク)

Py_*Main

int Py_Main(int argc, wchar_t **argv)

<概説>

標準インタプリタのためのメインプログラム。argcargv引数をCプログラムのmain()関数へ渡す。
戻り値はインタプリタが(例外などではなく)普通に終了した時は0に、例外で終了したときには 1に、引数リストが正しい Python コマンドラインが渡されなかったときは2になる。

<定義>

定義 (cpython/Modules/main.c)
int
Py_Main(int argc, wchar_t **argv)
{
    _PyArgv args = {
        .argc = argc,
        .use_bytes_argv = 0,
        .bytes_argv = NULL,
        .wchar_argv = argv};
    return pymain_main(&args);
}

(定義出典)

<使用例>

使用例 (cpython/Programs/python.c)
int
wmain(int argc, wchar_t **argv)
{
    return Py_Main(argc, argv);
}

(使用例出典)

int Py_BytesMain(int argc, char **argv)

<概説>

Py_Main()argvbytes stringsarrayにしたもの。

<定義>

定義 (cpython/Modules/main.c)
int
Py_BytesMain(int argc, char **argv)
{
    _PyArgv args = {
        .argc = argc,
        .use_bytes_argv = 1,
        .bytes_argv = argv,
        .wchar_argv = NULL};
    return pymain_main(&args);
}

(定義出典)

<使用例>

使用例 (cpython/Programs/python.c)
int
main(int argc, char **argv)
{
    return Py_BytesMain(argc, argv);
}

(使用例出典)

PyRun_AnyFile*

int PyRun_AnyFile(FILE *fp, const char *filename)

<概説>

下記のPyRun_AnyFileExFlags()closeit0に、flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_AnyFile(FILE *fp, const char *name)
{
    return PyRun_AnyFileExFlags(fp, name, 0, NULL);
}

(定義出典)

<使用例>

使用例 (cpython/Python/frozenmain.c)
        sts = PyRun_AnyFile(stdin, "<stdin>") != 0;

(使用例出典)

int PyRun_AnyFileFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)

<概説>

下記のPyRun_AnyFileExFlags()closeit0にして単純化したインターフェース。

<定義>

定義 (cpython/Include/cpython/pythonrun.h)
#define PyRun_AnyFileFlags(fp, name, flags) \
    PyRun_AnyFileExFlags(fp, name, 0, flags)

(定義出典)

<使用例>

使用例 (cpython/Modules/main.c)
    PyCompilerFlags cf = _PyCompilerFlags_INIT;
    int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf);

(使用例出典)

int PyRun_AnyFileEx(FILE *fp, const char *filename, int closeit)

<概説>

下記のPyRun_AnyFileExFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Include/cpython/pythonrun.h)
PyAPI_FUNC(int)
PyRun_AnyFileEx(FILE *fp, const char *name, int closeit)
{
    return PyRun_AnyFileExFlags(fp, name, closeit, NULL);
}

(定義出典)

<使用例>

CPython中には特に見当たらなかった。

int PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags)

<概説>

fpが対話的デバイス (コンソールや端末入力あるいは Unix 仮想端末) と関連づけられたファイルを参照している場合は、PyRun_InteractiveLoop()の値を返す。
それ以外の場合は、PyRun_SimpleFile()の結果を返す。

<定義>

定義 (cpython/Python/pythonrun.c)
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
                     PyCompilerFlags *flags)
{
    PyObject *filename_obj;
    if (filename != NULL) {
        filename_obj = PyUnicode_DecodeFSDefault(filename);
        if (filename_obj == NULL) {
            PyErr_Print();
            return -1;
        }
    }
    else {
        filename_obj = NULL;
    }
    int res = _PyRun_AnyFileObject(fp, filename_obj, closeit, flags);
    Py_XDECREF(filename_obj);
    return res;
}

(定義出典)

<使用例>

使用例 (cpython/Modules/main.c)
static int
pymain_run_stdin(PyConfig *config)
{
...
    int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
}

(使用例出典)

PyRun_SimpleString*

int PyRun_SimpleString(const char *command)

<概説>

下記のPyRun_SimpleStringFlags()argumentNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_SimpleString(const char *s)
{
    return PyRun_SimpleStringFlags(s, NULL);
}

(定義出典)

<使用例>

使用例 (cpython/Programs/_testembed.c)
    PyRun_SimpleString(
        "import sys;"
        "print('id(modules) =', id(sys.modules));"
        "sys.stdout.flush()"
    );

(使用例出典)

int PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)

<概説>

__main__ モジュールの中でflagsに従ってcommandに含まれるPythonソースコードを実行する。
正常終了の場合は0を返し、また例外が発生した場合は-1を返す。

<定義>

定義 (cpython/Python/pythonrun.c)
int
PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
{
    PyObject *m, *d, *v;
    m = PyImport_AddModule("__main__");
    if (m == NULL)
        return -1;
    d = PyModule_GetDict(m);
    v = PyRun_StringFlags(command, Py_file_input, d, d, flags);
    if (v == NULL) {
        PyErr_Print();
        return -1;
    }
    Py_DECREF(v);
    return 0;
}

(定義出典)

<使用例>

使用例 (cpython/Modules/main.c)
static int
pymain_run_command(wchar_t *command)
{
...
    ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf);

(使用例出典)

PyRun_SimpleFile*

int PyRun_SimpleFile(FILE *fp, const char *filename)

<概説>

下記のPyRun_SimpleFileExFlags()closeit0に、flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_SimpleFile(FILE *f, const char *p)
{
    return PyRun_SimpleFileExFlags(f, p, 0, NULL);
}

(定義出典)

<使用例>

CPython中には、明らかな使用例は見当たらなかった。

int PyRun_SimpleFileEx(FILE *fp, const char *filename, int closeit)

<概説>

下記のPyRun_SimpleFileExFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_SimpleFileEx(FILE *f, const char *p, int c)
{
    return PyRun_SimpleFileExFlags(f, p, c, NULL);
}

(定義出典)

<使用例>

CPython中には、明らかな使用例は見当たらなかった。

int PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags)

<概説>

PyRun_SimpleStringFlags()と似ているが、Pythonソースコードをメモリ内の文字列ではなくfpから読み込む。
filenameはそのファイルの名前でなければならない。
closeitに真を指定した場合は、PyRun_SimpleFileExFlagsが処理を戻す前にファイルを閉じる。

<定義>

定義 (cpython/Python/pythonrun.c)
int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
                        PyCompilerFlags *flags)
{
    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
    if (filename_obj == NULL) {
        return -1;
    }
    int res = _PyRun_SimpleFileObject(fp, filename_obj, closeit, flags);
    Py_DECREF(filename_obj);
    return res;
}

(定義出典)

<使用例>

上記、int PyRun_SimpleFileEx(FILE *fp, const char *filename, int closeit)参照。

PyRun_Interactive*

int PyRun_InteractiveOne(FILE *fp, const char *filename)

<概説>

下記のPyRun_InteractiveOneFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_InteractiveOne(FILE *f, const char *p)
{
    return PyRun_InteractiveOneFlags(f, p, NULL);
}

(定義出典)

<使用例>

CPython中には特に見当たらなかった。

int PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)

<概説>

対話的デバイスに関連付けられたファイルから文を一つ読み込み、flagsに従って実行する。
sys.ps1sys.ps2を使って、ユーザにプロンプトを表示する。

入力が正常に実行されたときは0を返し、例外が発生した場合は-1を返す。
パースエラーの場合はPythonの一部として配布されている errcode.hインクルードファイルにあるエラーコードを返す。
(Python.h は errcode.h をインクルードしないため、 必要な場合はその都度インクルードしなければならないことに注意。)

<定義>

定義 (cpython/Python/pythonrun.c)
int
PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)
{
    PyObject *filename;
    int res;

    filename = PyUnicode_DecodeFSDefault(filename_str);
    if (filename == NULL) {
        PyErr_Print();
        return -1;
    }
    res = PyRun_InteractiveOneObject(fp, filename, flags);
    Py_DECREF(filename);
    return res;
}

(定義出典)

<使用例>

上記PyRun_InteractiveOne参照。

int PyRun_InteractiveLoop(FILE *fp, const char *filename)

<概説>

下記のPyRun_InteractiveLoopFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(int)
PyRun_InteractiveLoop(FILE *f, const char *p)
{
    return PyRun_InteractiveLoopFlags(f, p, NULL);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

int PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)

<概説>

対話的デバイスに関連付けられたファイルからEOFに達するまで文を読み込み実行する。
sys.ps1sys.ps2を使って、ユーザにプロンプトを表示する。
EOFに達すると0を返すか、失敗したら負の数を返す。

<定義>

定義 (cpython/Python/pythonrun.c)
int
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
    if (filename_obj == NULL) {
        PyErr_Print();
        return -1;
    }

    int err = _PyRun_InteractiveLoopObject(fp, filename_obj, flags);
    Py_DECREF(filename_obj);
    return err;

}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyOS_*

int (*PyOS_InputHook)(void)

<概説>

int func(void)というプロトタイプの関数へのポインタが設定できる。
この関数は、 Python のインタプリタのプロンプトがアイドル状態になりターミナルからのユーザの入力を待つようになったときに呼び出され、返り値は無視される。
このフックを上書きすることで、 Python のソースコードの中で Modules/_tkinter.c がやっているように、インタプリタのプロンプトと他のイベントループを統合できる。

<定義>

定義 (cpython/Include/pythonrun.c)
PyAPI_DATA(int) (*PyOS_InputHook)(void);

(定義出典)

<使用例>

使用例 (cpython/Modules/readline.c)
static char *
readline_until_enter_or_signal(const char *prompt, int *signal)
{
...
            if(PyOS_InputHook) PyOS_InputHook();

(使用例出典)

char* (*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *)

<概説>

char *func(FILE *stdin, FILE *stdout, char *prompt)というプロトタイプの関数へのポインタが設定でき、
デフォルトの関数を上書きすることでインタプリタのプロンプトへの入力を1行だけ読める。
返り値は PyMem_RawMalloc()またはPyMem_RawRealloc()でメモリ確保した文字列、あるいはエラーが起きた場合にはNULLでなければならない。

<定義>

定義 (cpython/Include/pythonrun.c)
PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *);

(定義出典)

<使用例>

使用例 (cpython/Parser/myreadline.c)
char *
PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
{
...
        rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
                                             prompt);

(使用例出典)

PyParser_*

struct _node* PyParser_SimpleParseString(const char *str, int start)

<概説>

下記の PyParser_SimpleParseStringFlagsFilename() の filename を NULL に、 flags を 0 にして単純化したインタフェース。(will be deprecated)

<定義>

github上でコード定義見つけるのが困難なためpass.(branchを指定した検索の仕方がわからないため)

<使用例>

pass.

struct _node* PyParser_SimpleParseStringFlags(const char *str, int start, int flags)

<概説>

下記の PyParser_SimpleParseStringFlagsFilename() の filename を NULL にして単純化したインタフェース。(will be deprecated)

<定義>

github上でコード定義見つけるのが困難なためpass.(branchを指定した検索の仕方がわからないため)

<使用例>

pass.

struct _node* PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename, int start, int flags)

<概説>

開始トークン start を使って str に含まれる Python ソースコードを flags 引数に従ってパースする。
コード断片を何度も評価しなければならない場合に役に立つ。(will be deprecated)

<定義>

github上でコード定義見つけるのが困難なためpass.(branchを指定した検索の仕方がわからないため)

<使用例>

pass.

struct _node* PyParser_SimpleParseFile(FILE *fp, const char *filename, int start)

<概説>

下記の PyRun_SimpleParseFileFlags() の flags を 0 にして単純化したインターフェース。(will be deprecated)

<定義>

github上でコード定義見つけるのが困難なためpass.(branchを指定した検索の仕方がわからないため)

<使用例>

pass.

struct _node* PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int flags)

<概説>

PyParser_SimpleParseStringFlagsFilename() に似ているが、 Pythonソースコードをメモリ内の文字列ではなく fp から読み込む。(will be deprecated)

<定義>

github上でコード定義見つけるのが困難なためpass.(branchを指定した検索の仕方がわからないため)

<使用例>

pass.

PyRun_String*

PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)

<概説>

下記のPyRun_StringFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(PyObject *)
PyRun_String(const char *str, int s, PyObject *g, PyObject *l)
{
    return PyRun_StringFlags(str, s, g, l, NULL);
}

(定義出典)

<使用例>

使用例 (cpython/
static PyObject *
builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
                  PyObject *locals)
...
            v = PyRun_String(str, Py_file_input, globals, locals);

(使用例出典)

PyObject* PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags)

<概説>

オブジェクトの globals と locals で指定されるコンテキストで、コンパイラフラグに flags を設定した状態で、 str にある Python ソースコードを実行する。
globals は辞書でなければならない。locals はマッピングプロトコルを実装したオブジェクトなら何でも構わない。
引数 start はソースコードをパースするために使われるべき開始トークンを指定する。
コードを実行した結果をPythonオブジェクトとして返す。または、例外が発生したならば NULL を返す。

<定義>

定義 (cpython/Python/pythonrun.c)
PyObject *
PyRun_StringFlags(const char *str, int start, PyObject *globals,
                  PyObject *locals, PyCompilerFlags *flags)
{
    PyObject *ret = NULL;
    mod_ty mod;
    PyArena *arena;
    PyObject *filename;

    filename = _PyUnicode_FromId(&PyId_string); /* borrowed */
    if (filename == NULL)
        return NULL;

    arena = _PyArena_New();
    if (arena == NULL)
        return NULL;

    mod = _PyParser_ASTFromString(str, filename, start, flags, arena);

    if (mod != NULL)
        ret = run_mod(mod, filename, globals, locals, flags, arena);
    _PyArena_Free(arena);
    return ret;
}

(定義出典)

<使用例>

使用例 (cpython/Python/pythonrun.c)
int
PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
{
...
    v = PyRun_StringFlags(command, Py_file_input, d, d, flags);

(使用例出典)

PyRun_File*

PyObject* PyRun_File(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals)

<概説>

下記のPyRun_FileExFlags()closeit0にし、flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l)
{
    return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyObject* PyRun_FileEx(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals, int closeit)

<概説>

下記のPyRun_FileExFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(PyObject *)
PyRun_FileEx(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, int c)
{
    return PyRun_FileExFlags(fp, p, s, g, l, c, NULL);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyObject* PyRun_FileFlags(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags)

<概説>

下記のPyRun_FileExFlags()closeit0にして単純化したインターフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(PyObject *)
PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,
                PyCompilerFlags *flags)
{
    return PyRun_FileExFlags(fp, p, s, g, l, 0, flags);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyObject* PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags)

<概説>

PyRun_StringFlags()と似ているが、Pythonソースコードをメモリ内の文字列ではなくfpから読み込む。
filenameはそのファイルの名前でなければならない。
もしcloseitを真にすると、PyRun_FileExFlags()が処理を戻す前にファイルを閉じる。

Py_Compile*

PyObject* Py_CompileString(const char *str, const char *filename, int start)

<概説>

下記のPy_CompileStringFlags()flagsNULLにして単純化したインタフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyObject *
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
                  PyObject *locals, int closeit, PyCompilerFlags *flags)
{
    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
    if (filename_obj == NULL) {
        return NULL;
    }

    PyObject *res = pyrun_file(fp, filename_obj, start, globals,
                               locals, closeit, flags);
    Py_DECREF(filename_obj);
    return res;

}

(定義出典)

<使用例>

使用例 (cpython/Python/pythonrun.c)
PyAPI_FUNC(PyObject *)
PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l)
{
    return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL);
}

(使用例出典)

PyObject* Py_CompileStringFlags(const char *str, const char *filename, int start, PyCompilerFlags *flags)

<概説>

下記のPy_CompileStringExFlags()optimize-1にして単純化したインターフェース。

<定義>

定義 (cpython/Python/pythonrun.c)
PyAPI_FUNC(PyObject *)
Py_CompileStringFlags(const char *str, const char *p, int s,
                      PyCompilerFlags *flags)
{
    return Py_CompileStringExFlags(str, p, s, flags, -1);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyObject* Py_CompileStringObject(const char *str, PyObject *filename, int start, PyCompilerFlags *flags, int optimize)

<概説>

str内のPythonソースコードをパースしてコンパイルし、作られたコードオブジェクトを返す。
開始トークンはstartによって与えられる。
filenameで指定されるファイル名はコードオブジェクトを構築するために使われ、トレースバックあるいは SyntaxError例外メッセージに出てくる可能性がある。
コードがパースできなかったりコンパイルできなかったりした場合に、これはNULLを返す。

整数optimizeは、コンパイラの最適化レベルを指定する; -1 は、インタプリタの -O オプションで与えられるのと同じ最適化レベルを選ぶ。
明示的なレベルは、 0 (最適化なし、 debug は真)、 1 (assert は取り除かれ、 debug は偽)、 2 (docstring も取り除かれる) 。

<定義>

定義 (cpython/Python/pythonrun.c)
PyObject *
Py_CompileStringObject(const char *str, PyObject *filename, int start,
                       PyCompilerFlags *flags, int optimize)
{
    PyCodeObject *co;
    mod_ty mod;
    PyArena *arena = _PyArena_New();
    if (arena == NULL)
        return NULL;

    mod = _PyParser_ASTFromString(str, filename, start, flags, arena);
    if (mod == NULL) {
        _PyArena_Free(arena);
        return NULL;
    }
    if (flags && (flags->cf_flags & PyCF_ONLY_AST)) {
        PyObject *result = PyAST_mod2obj(mod);
        _PyArena_Free(arena);
        return result;
    }
    co = _PyAST_Compile(mod, filename, flags, optimize, arena);
    _PyArena_Free(arena);
    return (PyObject *)co;
}

(定義出典)

<使用例>

使用例 (cpython/
PyObject *
Py_CompileStringExFlags(const char *str, const char *filename_str, int start,
                        PyCompilerFlags *flags, int optimize)
{
...
    co = Py_CompileStringObject(str, filename, start, flags, optimize);

(使用例出典)

PyObject* Py_CompileStringExFlags(const char *str, const char *filename, int start, PyCompilerFlags *flags, int optimize)

<概説>

Py_CompileStringObject()と似ているが、filenameはファイルシステムのエンコーディングでデコード (os.fsdecode()) されたバイト文字列。

<定義>

定義 (cpython/Python/pythonrun.c)
PyObject *
Py_CompileStringExFlags(const char *str, const char *filename_str, int start,
                        PyCompilerFlags *flags, int optimize)
{
    PyObject *filename, *co;
    filename = PyUnicode_DecodeFSDefault(filename_str);
    if (filename == NULL)
        return NULL;
    co = Py_CompileStringObject(str, filename, start, flags, optimize);
    Py_DECREF(filename);
    return co;
}

(定義出典)

<使用例>

使用例 (cpython/Programs/_freeze_importlib.c)
int
main(int argc, char *argv[])
{
...
    code = Py_CompileStringExFlags(text, buf, Py_file_input, NULL, 0);

(使用例出典)

PyEval_*

PyObject* PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)

<概説>

PyEval_EvalCodeEx()のシンプルなインタフェースで、コードオブジェクトと、グローバル変数とローカル変数だけを受け取る。 他の引数にはNULLが渡される。

<定義>

定義 (cpython/Python/ceval.c)
PyObject *
PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
{
    PyThreadState *tstate = PyThreadState_GET();
    if (locals == NULL) {
        locals = globals;
    }
    PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref
    if (builtins == NULL) {
        return NULL;
    }
    PyFrameConstructor desc = {
        .fc_globals = globals,
        .fc_builtins = builtins,
        .fc_name = ((PyCodeObject *)co)->co_name,
        .fc_qualname = ((PyCodeObject *)co)->co_name,
        .fc_code = co,
        .fc_defaults = NULL,
        .fc_kwdefaults = NULL,
        .fc_closure = NULL
    };
    return _PyEval_Vector(tstate, &desc, locals, NULL, 0, NULL);
}

(定義出典)

<使用例>

使用例 (cpython/Python/pythonrun.c)
static PyObject *
run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, PyObject *locals)
{
...
    v = PyEval_EvalCode((PyObject*)co, globals, locals);
...
    return v;
}

(使用例出典)

PyObject* PyEval_EvalCodeEx(PyObject *co, PyObject *globals, PyObject *locals, PyObject *const *args, int argcount, PyObject *const *kws, int kwcount, PyObject *const *defs, int defcount, PyObject *kwdefs, PyObject *closure)

<概説>

与えられた特定の環境で、コンパイル済みのコードオブジェクトを評価する。この環境はグローバル変数の辞書と、ローカル変数のマッピングオブジェクト、引数の配列、キーワードとデフォルト値、キーワード専用 引数のデフォルト値の辞書と、セルのクロージャタプルで構成される。

<定義>

定義 (cpython/Python/ceval.c)
PyObject *
PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
                  PyObject *const *args, int argcount,
                  PyObject *const *kws, int kwcount,
                  PyObject *const *defs, int defcount,
                  PyObject *kwdefs, PyObject *closure)
{
    PyThreadState *tstate = _PyThreadState_GET();
...
    PyFrameConstructor constr = {
        .fc_globals = globals,
        .fc_builtins = builtins,
        .fc_name = ((PyCodeObject *)_co)->co_name,
        .fc_qualname = ((PyCodeObject *)_co)->co_name,
        .fc_code = _co,
        .fc_defaults = defaults,
        .fc_kwdefaults = kwdefs,
        .fc_closure = closure
    };
    res = _PyEval_Vector(tstate, &constr, locals,
                         allargs, argcount,
                         kwnames);
...
    return res;
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyFrameObject

<概説>

フレームオブジェクトを表現するために使われるオブジェクトのC構造体。 この型のフィールドはいつでも変更され得る。

<定義>

定義 (cpython/Include/frameobject.h)
typedef struct _frame {
    PyObject_VAR_HEAD
    struct _frame *f_back;      /* previous frame, or NULL */
    PyCodeObject *f_code;       /* code segment */
    PyObject *f_builtins;       /* builtin symbol table (PyDictObject) */
    PyObject *f_globals;        /* global symbol table (PyDictObject) */
    PyObject *f_locals;         /* local symbol table (any mapping) */
    PyObject **f_valuestack;    /* points after the last local */
    /* Next free slot in f_valuestack.  Frame creation sets to f_valuestack.
       Frame evaluation usually NULLs it, but a frame that yields sets it
       to the current stack top. */
    PyObject **f_stacktop;
    PyObject *f_trace;          /* Trace function */
    char f_trace_lines;         /* Emit per-line trace events? */
    char f_trace_opcodes;       /* Emit per-opcode trace events? */

    /* Borrowed reference to a generator, or NULL */
    PyObject *f_gen;

    int f_lasti;                /* Last instruction if called */
    /* Call PyFrame_GetLineNumber() instead of reading this field
       directly.  As of 2.3 f_lineno is only valid when tracing is
       active (i.e. when f_trace is set).  At other times we use
       PyCode_Addr2Line to calculate the line from the current
       bytecode index. */
    int f_lineno;               /* Current line number */
    int f_iblock;               /* index in f_blockstack */
    char f_executing;           /* whether the frame is still executing */
    PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
    PyObject *f_localsplus[1];  /* locals+stack, dynamically sized */
} PyFrameObject;

(定義出典)

<使用例>

使用例 (cpython/Objects/frameobject.c)
PyFrameObject* _Py_HOT_FUNCTION
_PyFrame_New_NoTrack(PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals)
{
...
    PyFrameObject *f = frame_alloc((PyCodeObject *)con->fc_code);
...
    f->f_back = (PyFrameObject*)Py_XNewRef(tstate->frame);
    f->f_code = (PyCodeObject *)Py_NewRef(con->fc_code);
    f->f_builtins = Py_NewRef(con->fc_builtins);
    f->f_globals = Py_NewRef(con->fc_globals);
    f->f_locals = Py_XNewRef(locals);
    // f_valuestack initialized by frame_alloc()
    f->f_trace = NULL;
    f->f_stackdepth = 0;
    f->f_trace_lines = 1;
    f->f_trace_opcodes = 0;
    f->f_gen = NULL;
    f->f_lasti = -1;
    f->f_lineno = 0;
    f->f_iblock = 0;
    f->f_state = FRAME_CREATED;
    // f_blockstack and f_localsplus initialized by frame_alloc()
    return f;
}

(使用例出典)

PyObject* PyEval_EvalFrame(PyFrameObject *f)

<概説>

実行フレームを評価する。これはPyEval_EvalFrameEx()に対するシンプルなインターフェースで、後方互換性のためのもの。

<定義>

定義 (cpython/Python/ceval.c)
PyObject *
PyEval_EvalFrame(PyFrameObject *f)
{
    /* Function kept for backward compatibility */
    PyThreadState *tstate = _PyThreadState_GET();
    return _PyEval_EvalFrame(tstate, f, 0);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

PyObject* PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)

<概説>

Python interpretationのありのままのmain関数。
execution frame fに関連したコードオブジェクトが実行され、必要に応じてbytecodeが翻訳され、呼び出しが行われる。

<定義>

定義 (cpython/Python/ceval.c)
PyObject *
PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
{
    PyThreadState *tstate = _PyThreadState_GET();
    return _PyEval_EvalFrame(tstate, f, throwflag);
}

(定義出典)

<使用例>

CPython中には明らかな使用例は見当たらなかった。

int PyEval_MergeCompilerFlags(PyCompilerFlags *cf)

<概説>

現在の評価フレームのフラグを変更する。成功したら true を、失敗したら false を返す。

<定義>

定義 (cpython/Python/ceval.c)
int
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
{
    PyThreadState *tstate = _PyThreadState_GET();
    PyFrameObject *current_frame = tstate->frame;
    int result = cf->cf_flags != 0;

    if (current_frame != NULL) {
        const int codeflags = current_frame->f_code->co_flags;
        const int compilerflags = codeflags & PyCF_MASK;
        if (compilerflags) {
            result = 1;
            cf->cf_flags |= compilerflags;
        }
    }
    return result;
}

(定義出典)

<使用例>

使用例 (cpython/Python/bltinmodule.c)
    if (!dont_inherit) {
        PyEval_MergeCompilerFlags(&cf);
    }

(使用例出典)

int Py_eval_input

<概説>

単独の式に対するPython文法の開始記号で、Py_CompileString()と一緒に使う。

<定義>

定義 (cpython/Include/compile.h)
#define Py_eval_input 258

(定義出典)

<使用例>

使用例 (cpython/Modules/symtablemodule.c)
    else if (strcmp(startstr, "eval") == 0)
        start = Py_eval_input;

(使用例出典)

int Py_file_input

<概説>

ファイルあるいは他のソースから読み込まれた文の並びに対するPython文法の開始記号で、 Py_CompileString()と一緒に使う。

<定義>

定義 (cpython/Include/compile.h)
#define Py_file_input 257

(定義出典)

<使用例>

使用例 (cpython/Modules/symtablemodule.c)
    if (strcmp(startstr, "exec") == 0)
        start = Py_file_input;

(使用例出典)

int Py_single_input

<概説>

単一の文に対するPython文法の開始記号で、Py_CompileString()と一緒に使う。これは対話式のインタプリタループのための記号。

<定義>

定義 (cpython/Include/compile.h)
#define Py_single_input 256

(定義出典)

<使用例>

使用例 (cpython/Modules/symtablemodule.c)
    else if (strcmp(startstr, "single") == 0)
        start = Py_single_input;

(使用例出典)

struct PyCompilerFlags

<概説>

コンパイラフラグを収めておくための構造体。
コードをコンパイルするだけの場合、この構造体がint flagsとして渡される。
コードを実行する場合にはPyCompilerFlags *flagsとして渡される。

<定義>

定義 (cpython/Include/compile.h)
typedef struct {
    int cf_flags;  /* bitmask of CO_xxx flags relevant to future */
} PyCompilerFlags;

(定義出典)

<使用例>

使用例 (cpython/Modules/main.c)
static void
pymain_run_python(_PyMain *pymain)
{
    PyCompilerFlags cf = {.cf_flags = 0};

(使用例出典)

int cf_flags

<概説>

Compiler flags.

<定義>

直上参照。

int cf_feature_version

<概説>

省略。

int CO_FUTURE_DIVISION

<概説>

このビットを flags にセットすると、除算演算子 / は PEP 238 による「真の除算 (true division)」として扱われる。

<定義>

定義 (cpython/Include/code.h)
#define CO_FUTURE_DIVISION      0x2000

(定義出典)

<使用例>

明らかには見つけられず。

参考にさせていただいた本・ページ

感想

バージョンが混ざってしまっているが、雰囲気を掴みたかっただけなので、そこは厳密にはしなかった。
使用例については、CPythonの中で用いられているものに限定した。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3