使用 Python3 C API 添加到内置函数

Using Python3 C API to add to builtins

我希望使用 Python3 C API 添加内置函数。我这样做只是为了帮助我熟悉 Python C API。 this 问题的答案很好地解释了为什么人们可能不想这样做。无论如何,我想在 Python builtins 模块中添加一个函数 foo

这是我目前所做的 (foo.c):

#include <Python.h>
#include <stdio.h>

static PyObject*
foo(PyObject *self, PyObject *args){
    printf("foo called");
    return Py_None;
}

char builtin_name[] = "builtins";
char foo_name[] = "foo";
char foo_doc[] = "foo function";

static PyMethodDef foo_method = {foo_name, foo, METH_NOARGS, foo_doc};

PyMODINIT_FUNC
PyInit_foo(void){
    PyObject *builtin_module = PyImport_ImportModule(builtin_name);
    PyModule_AddFunctions(builtin_module, &foo_method);
    return builtin_module;
}

我将它放在 Python 源目录的 Modules/ 目录中。

仅仅因为你把它放在Modules/文件夹中并使用Python-C-API并不意味着它会自动编译和执行。在将 foo.c 编译为 Python 扩展模块后(你做到了,对吗?)你的代码(大致)等同于:

foo.py

def foo():
    """foo function"""
    print("foo called")

import builtins
builtins.foo = foo

在 Python 实现中不是那么简单的事实是当你 import foo 它不会 return 你的 foo 模块而是 builtins.但我想说这根本不是一个好主意,特别是因为你想要添加的内置函数与你创建的模块同名,所以很可能 import foo 你实际上覆盖了手动添加的 builtins.foo 再次...

除此之外:仅仅将它放在 Modules/ 文件夹中并不意味着它在您启动 Python 时实际上已被导入。您需要自己使用 import foo 或修改您的 Python 启动以导入它。

好的,除此之外你应该问自己以下问题:

  • 你想自己编译Python吗?如果是,那么你可以简单地编辑Python/文件夹中的bltinsmodule.c,然后完全编译Python。
  • 除了完整的 Python 之外,您还想编译任何东西吗?如果是,那么就创建你自己的扩展模块(基本上就像你已经做的那样)但不要把它放在 Python 的 Modules/ 文件夹中,而是真正创建一个包(完成 setup.py等等)并且不要 return 模块初始化中的 builtins 模块。在将 foo 添加到 builtins 模块后,只需创建一个空模块并 return 它。并使用不同的模块名称,也许 _foo 这样它就不会与新添加的 builtins.foo 函数冲突。
  • 在这种情况下,Python-C-API 和扩展模块是否正确?如果您认为 Python-C-API 会使添加到 builtins 更容易,那您就错了。 Python-C-API 只允许更快地访问和更多地访问 Python 功能。如果你只想做 Python 的事情(而不是与 C 接口图书馆)。我会说,对于您的用例,创建扩展模块完全是矫枉过正,所以也许只使用普通的 Python 模块。

我的建议是使用上面提到的 foo.py 并让 Python 在启动时导入它。为此,您将 foo.py 文件(我真的建议您将名称更改为 _foo.py 之类的名称)放在安装附加包的目录中(site-packages on windows)并使用 PYTHONSTARTUP(或另一种自定义启动的方法)在 Python 启动时导入该模块。