相当于Python C API中的__all__

时间:2018-06-13 19:34:59

标签: python python-c-api

我正在使用C API编写一个简单的扩展模块。这是一个测试示例:

#include <Python.h>
#include <structmember.h>

typedef struct {
    PyObject_HEAD
    int i;
} MyObject;

static PyMemberDef my_members[] = {
    {"i", T_INT, offsetof(MyObject, i), READONLY, "Some integer"},
    {NULL}  /* Sentinel */
};


static int MyType_init(MyObject *self, PyObject *args, PyObject *kwds)
{
    char *keywords[] = {"i", NULL};
    int i = 0;

    if(!PyArg_ParseTupleAndKeywords(args, kwds, "|i", keywords, &i)) {
        return -1;
    }
    self->i = i;
    return 0;
}

static PyTypeObject MyType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "_my.MyType",
    .tp_doc = "Pointless placeholder class",
    .tp_basicsize = sizeof(MyObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    .tp_init = (initproc)MyType_init,
    .tp_members = my_members,
};

static PyModuleDef my_module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "_my",
    .m_doc = "My module is undocumented!",
    .m_size = -1,
};

/* Global entry point */

PyMODINIT_FUNC PyInit__my(void)
{
    PyObject *m = NULL;

    PyExc_MyException = PyErr_NewExceptionWithDoc("_my.MyException",
        "Indicates that something went horribly wrong.",
        NULL, NULL);
    if(PyExc_MyException == NULL) {
        return NULL;
    }

    if(PyType_Ready(&MyType) < 0) {
        goto err;
    }

    if((m = PyModule_Create(&my_module)) == NULL) {
        goto err;
    }

    Py_INCREF(&MyType);
    PyModule_AddObject(m, "MyType", (PyObject *)&MyType);
    PyModule_AddObject(m, "MyException", (PyObject *)PyExc_MyException);

    return m;

err:
    Py_CLEAR(PyExc_MyException);
    return NULL;
}

此模块包含一个类MyType和一个例外MyException。此模块的目的是为使用Python编写的一些其他代码提供基本功能。我希望能够做到这样的事情:

my.py

from _my import *

class MyType(MyType):
    def __init__(i=0):
        raise MyException

显然这个例子非常人为。我只想说明如何使用my扩展名中的名称。现在导入工作正常,根据rule

  

如果未定义__all__,则公共名称集包括在模块命名空间中找到的所有名称,这些名称不以下划线字符('_')开头。

但是,我希望有更好的控制水平。到目前为止,我能够想到的是手动向模块添加__all__属性:

    PyObject *all = NULL;
    ...
    all = Py_BuildValue("[s, s]", "MyType", "MyException");
    if(all == NULL) {
        goto err;
    }
    PyModule_AddObject(m, "__all__", all);
    ...
err:
    ...
    Py_CLEAR(all);

这看起来有点笨重。 C API中是否有一个函数用于为模块定义__all__的内部等效项?

我认为可能存在内部等效的部分原因是__all__毕竟是dunder属性。

0 个答案:

没有答案