使用 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 启动时导入该模块。
我希望使用 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 启动时导入该模块。