كيفية استيراد ملف بواسطة مساره الكامل باستخدام C API؟
-
22-09-2019 - |
سؤال
pyobject * pyimport_importmodule (const char * name)
كيفية تحديد مسار الملف الكامل بدلاً من ذلك واسم الوحدة النمطية؟
مثل PyImport_SomeFunction(const char *path_to_script, const char *name)
شكرا ، إلياس
المحلول 4
في النهاية ، انتهى بي الأمر باستخدام load_source من وحدة IMP:
s.sprintf(
"import imp\n"
"imp.load_source('%s', r'%s')", modname, script_path);
PyRun_SimpleString(s.c_str());
أعتقد أنه الحل الأكثر جدوى. اقتراحات أخرى موضع ترحيب.
نصائح أخرى
حل آخر للحالات التي يكون فيها جميع ملف *.py في دليل واحد:
PySys_SetPath("path/with/python/files");
PyObject *pModule = PyImport_ImportModule("filename_without_extension");
لا أستطيع أن أعطيك إجابة كاملة ، لكنني أعتقد أنني أستطيع أن أعطيك مكانًا للبدء. يوفر Python وحدة نمطية مدمجة تسمى imp
الذي يوفر الوصول إلى الاستيراد الداخلية. ويشمل وظيفة load_module () والتي تتيح لك المرور في مسار. يتم تنفيذ هذا في بيثون/استيراد; ؛ فقط ابحث عن imp_load_module
.
كما أشير ، باستخدام الحل أعلاه بواسطة Alexp ، لا يمكنك استيراد أي وحدات خارج الدليل المحدد. ومع ذلك ، بدلا من إعداد المسار ، يمكنك يضيف مسار ، يتم البحث عن وحدات. يمكن القيام بذلك عن طريق إلحاق هذا المسار Sys.path. لسوء الحظ ، لا تعرض API C وظيفة قادرة على القيام بذلك مباشرة. بدلاً من ذلك ، يمكنك أن تطلب من Python نفسه القيام بذلك ، باستخدام
PyRun_SimpleString( "import sys\nsys.path.append(\"<insert folder path>\")\n" );
أو أي ما يعادل: (تحذير: لم يخبر)
PyObject* sys = PyImport_ImportModule( "sys" );
PyObject* sys_path = PyObject_GetAttrString( sys, "path" );
PyObject* folder_path = PyUnicode_FromString( "<insert folder path>" );
PyList_Append( sys_path, folder_path );
الآن يمكنك استيراد أي ملف <insert folder path>/<file>.py
باستخدام المعتاد
PyObject* mymodule = PyImport_ImportModule( "<file>" );
للإشارة إلى الدليل الحالي ، ما عليك سوى الاستخدام "."
كمسار المجلد.
سوف cpython لا تتردد للاتصال من خلال imp
الوحدة النمطية لأداء وظائف الاستيراد ، لذلك لا يوجد سبب لعدم القيام بذلك بنفسك.
إليك طريقة واحدة للقيام بذلك في C ++ ، حيث modulePath
و moduleName
هي متغيرات منفصلة بسبب الكسل:
PyObject* loadModule(const char* modulePath, const char* moduleName)
{
auto modules = PyImport_GetModuleDict();
auto impModule = PyDict_GetItemString(modules, "imp");
if (impModule)
{
// GetItemString returns a borrowed reference, but ImportModule
// returns a new reference, so INCREF here to even it out
Py_INCREF(impModule);
}
else
{
impModule = PyImport_ImportModule("imp");
if (!impModule)
{
// we've tried hard enough, bail out
PyErr_Print();
return nullptr;
}
}
// The Python API asks for non-const char pointers :(
char methodName[] = "load_source";
char args[] = "ss";
auto module = PyObject_CallMethod(impModule, methodName, args, moduleName, modulePath);
Py_XDECREF(impModule);
Py_XDECREF(modulePath);
return module;
}
لقد كتبت هذا على أساس أحد محمل وحدة بيثون, ، الذي يستخدم إدارة مربي الطين ، ولم أجرب هذا ، لذا استخدم على مسؤوليتك الخاصة.
لقد تحقق من أن بديل SteM يعمل.
بغض النظر عن الحل الذي يتم استخدامه ، من المهم أن نذكر أنه من المهم في Windows أن يكون لديك المسار الكامل مع القطع المائلة بدلاً من الذرات الخلفية.
path = "C:\\path\\to\\module\\module.py" // wrong
path = "C:/path/to/module/module.py" // correct
في بعض الأسئلة والإجابات الأخرى (مثل Windows Path في Python) وذكر أن البديل الأول يجب أن يعمل أيضا. لم أستطع تشغيله بهذه الطريقة مهما كانت الطريقة التي جربتها.