كيفية استيراد ملف بواسطة مساره الكامل باستخدام C API؟

StackOverflow https://stackoverflow.com/questions/1796925

  •  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) وذكر أن البديل الأول يجب أن يعمل أيضا. لم أستطع تشغيله بهذه الطريقة مهما كانت الطريقة التي جربتها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top