PyImport_ImportModule() 的性能如何,使用它的最佳实践是什么?
What's the performance of PyImport_ImportModule(), and what are the best practices for using it?
我有一个内部循环 C 函数,它(在我的例子中)构造了一个 Python datetime
对象:
PyObject* my_inner_loop_fn(void* some_data) {
PyObject* datetime = PyImport_ImportModule("datetime");
if (datetime == NULL) return NULL;
PyObject* datetime_date = PyObject_GetAttrString(datetime, "date");
PyObject* result = NULL;
if (datetime_date != NULL) {
/* long long my_year, my_month, my_day = ... ; */
PyObject* args = Py_BuildValue("(LLL)", my_year, my_month, my_day);
res = PyObject_Call(datetime_date, args, NULL);
Py_XDECREF(args);
}
Py_XDECREF(datetime_date);
Py_DECREF(datetime);
return result;
}
我的问题:
PyImport_ImportModule("datetime")
是每次都从头重新加载整个模块,还是缓存了?
- 如果没有缓存:
- 缓存它的首选方法是什么?
- 最早什么时候可以安全地尝试导入其他模块?例如,我可以将它分配给全局变量吗?
我想避免为导入付出高昂的代价,因为函数运行频繁。以上是高性能代码吗?
Does the PyImport_ImportModule("datetime")
reload the entire module from scratch every time, or is it cached?
标准行为是 to first check sys.modules
to see if the module has already been imported 和 return 如果可能的话。只有导入不成功才重新加载
您显然可以自己测试,方法是将一些具有可见副作用的代码放入模块中并多次导入(例如打印语句)。
模块导入系统 是 可自定义的,所以我相信另一个模块可以选择修改该行为(例如, pyximport
模块有一个选项总是重新加载)。因此,不能 100% 保证。
它可能仍然值得缓存,因为进行查找会产生一些成本 - 这是不必自己缓存它的便利性和速度之间的平衡。
When is the earliest time it is safe to try importing the other module?
Python解释器初始化后就安全了。如果您要将 Python 嵌入到 C/C++ 程序中,这是您需要考虑的事情。如果您正在编写 Python 扩展模块,那么您可以确信解释器已针对要导入的模块进行了初始化。
Can I assign it to a global variable, for example?
是的。但是,全局变量使您的模块难以支持干净地卸载和重新加载。许多 C 扩展选择不担心这个。但是,PyModule_GetState
机制旨在支持此用例,因此您可以选择将缓存置于扩展模块状态。
我有一个内部循环 C 函数,它(在我的例子中)构造了一个 Python datetime
对象:
PyObject* my_inner_loop_fn(void* some_data) {
PyObject* datetime = PyImport_ImportModule("datetime");
if (datetime == NULL) return NULL;
PyObject* datetime_date = PyObject_GetAttrString(datetime, "date");
PyObject* result = NULL;
if (datetime_date != NULL) {
/* long long my_year, my_month, my_day = ... ; */
PyObject* args = Py_BuildValue("(LLL)", my_year, my_month, my_day);
res = PyObject_Call(datetime_date, args, NULL);
Py_XDECREF(args);
}
Py_XDECREF(datetime_date);
Py_DECREF(datetime);
return result;
}
我的问题:
PyImport_ImportModule("datetime")
是每次都从头重新加载整个模块,还是缓存了?- 如果没有缓存:
- 缓存它的首选方法是什么?
- 最早什么时候可以安全地尝试导入其他模块?例如,我可以将它分配给全局变量吗?
我想避免为导入付出高昂的代价,因为函数运行频繁。以上是高性能代码吗?
Does the
PyImport_ImportModule("datetime")
reload the entire module from scratch every time, or is it cached?
标准行为是 to first check sys.modules
to see if the module has already been imported 和 return 如果可能的话。只有导入不成功才重新加载
您显然可以自己测试,方法是将一些具有可见副作用的代码放入模块中并多次导入(例如打印语句)。
模块导入系统 是 可自定义的,所以我相信另一个模块可以选择修改该行为(例如, pyximport
模块有一个选项总是重新加载)。因此,不能 100% 保证。
它可能仍然值得缓存,因为进行查找会产生一些成本 - 这是不必自己缓存它的便利性和速度之间的平衡。
When is the earliest time it is safe to try importing the other module?
Python解释器初始化后就安全了。如果您要将 Python 嵌入到 C/C++ 程序中,这是您需要考虑的事情。如果您正在编写 Python 扩展模块,那么您可以确信解释器已针对要导入的模块进行了初始化。
Can I assign it to a global variable, for example?
是的。但是,全局变量使您的模块难以支持干净地卸载和重新加载。许多 C 扩展选择不担心这个。但是,PyModule_GetState
机制旨在支持此用例,因此您可以选择将缓存置于扩展模块状态。