防止从Python调用C类型

时间:2009-07-03 14:49:32

标签: python cpython

阻止从Python调用C类型(创建实例)的正确方法是什么?

我考虑提供引发异常的tp_init,但据我了解,仍然可以直接在该类型上调用__new__

C函数返回此类型的实例 - 这是打算创建此类实例的唯一方法。

编辑:我的意图是,如果我的用户不小心误用它,我会遇到异常。 C代码是这样的,调用从Python错误创建的对象上的函数会崩溃。我意识到这很不寻常:到目前为止,我所有的C扩展类型在从Python实例化时都运行良好。我的问题是是否有通常的方法来提供这种限制。

4 个答案:

答案 0 :(得分:3)

简单:将类型为tp_new的插槽留空。

>>> Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot create 'foo.Foo' instances
>>> Foo.__new__(Foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object.__new__(foo.Foo) is not safe, use foo.Foo.__new__()

如果从基础对象类型以外的类型继承,则必须在调用PyType_Ready()之后将tp_new设置为NULL。

答案 1 :(得分:1)

不要阻止他们这样做。 “We're all consenting adults here”。

除非他们有理由,否则没有人会这样做,如果他们有这样的理由那么你就不应该因为你没有预料到你的类型的所有可能用途而停止它们。

答案 2 :(得分:0)

“类型是另一个C函数的返回类型 - 这是打算创建此类实例的唯一方法” - 这相当令人困惑。我认为你的意思是“一个C函数返回这种类型的实例 - 这是唯一的方式等等”。

在您的文档中,明确警告来电者不要调用该类型。不要从C扩展名中导出类型。对于那些反省返回实例的人来说,你做不了多少但是那又怎样呢?这是他们的数据/机器/工作风险,而不是你的。

[更新(我讨厌用户界面评论!)]

詹姆斯:“类型......只是从C创建”:你再次混淆了类型及其实例。该类型在C中静态创建。您的C代码包含用户要调用以获取该类型实例的类型和工厂函数。由于某些原因,你没有解释,如果用户通过直接调用类型获得实例,后续的instance.method()调用将崩溃(我认为你的意思是“调用对象上的函数”。叫我疯了,但不是你应该修复的错误吗?

重新“不要导出”:尝试“不要暴露”。

在您的C代码中,您将有类似的内容,其中列出了您的模块提供的所有API,包括类型和功能:

static struct PyMethodDef public_functions[] = {
   {"EvilType", (PyCFunction) py_EvilType, ......},
   /* omit above line and punters can't call it directly from Python */
   {"make_evil", (PyCFunction) py_make_evil, ......},
   ......,
   };

module = Py_InitModule4("mymodule", public_functions, module_doc, ...

答案 3 :(得分:0)

有一种奇妙的防弹方式。让人们创建对象,让Python崩溃。这应该会阻止他们非常有效地完成它。 ;)

此外,您可以强调类名称,以表明它应该是内部的。 (至少,我假设您也可以从C创建下划线的类名,我实际上并没有这样做过。)