Domanda

* PyObject PyImport_ImportModule (const char * name)

Come specificare un percorso completo del file, invece, e un nome del modulo?

Come PyImport_SomeFunction(const char *path_to_script, const char *name)

Grazie, Elias

È stato utile?

Soluzione 4

Alla fine, ho finito per usare il load_source dal modulo imp:

s.sprintf( 
  "import imp\n" 
  "imp.load_source('%s', r'%s')", modname, script_path); 
PyRun_SimpleString(s.c_str()); 

Credo che sia la soluzione più fattibile. Altri suggerimenti sono i benvenuti.

Altri suggerimenti

Un'altra soluzione per i casi in cui tutti i file * .py sono in una directory:

PySys_SetPath("path/with/python/files");
PyObject *pModule = PyImport_ImportModule("filename_without_extension");

Non posso dare una risposta completa, ma penso di poter dare un punto di partenza. Python fornisce un modulo chiamato imp incorporato che consente di accedere alle parti interne di importazione. Esso include una funzione load_module (), che consente di passare in un percorso. Questo è implementato in Python / import.c ; basta cercare imp_load_module.

Come sottolineato, utilizzando la soluzione di cui sopra da AlexP, non è possibile importare tutti i moduli di fuori della directory specificata. Tuttavia, invece di impostazione il percorso, è possibile Aggiungi un percorso, che è quello di essere alla ricerca di moduli. Questo può essere fatto aggiungendo quel percorso a sys.path . Purtroppo l'API C non espone una funzione che è in grado di farlo direttamente. Invece si può chiedere lo stesso Python per farlo, usando

PyRun_SimpleString( "import sys\nsys.path.append(\"<insert folder path>\")\n" );

o equivalente come: (attenzione: non testata)

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 );

Ora è possibile importare qualsiasi file <insert folder path>/<file>.py utilizzando il solito

PyObject* mymodule = PyImport_ImportModule( "<file>" );

Per fare riferimento alla directory corrente, è sufficiente utilizzare "." come il percorso della cartella.

a chiamare attraverso il modulo imp per eseguire i lavori di importazione, quindi non c'è ragione per cui non si deve fare da soli.

Ecco un modo per farlo in C ++, dove modulePath e moduleName sono variabili separate a causa della pigrizia:

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;
}

Ho scritto questo sulla base di uno dei miei progetti modulo Python loader , che utilizza la gestione refcount più elaborato, e non ho provato questo, in modo da utilizzare a proprio rischio.

ho verificato che l'alternativa di stesim funziona.

è usato Non importa quale soluzione, è importante ricordare che sulle finestre è importante avere il percorso completo con barre al posto di backslash.

path = "C:\\path\\to\\module\\module.py" // wrong
path = "C:/path/to/module/module.py"     // correct

In alcune altre domande e risposte (come percorso di Windows in python ) si afferma, che la prima variante dovrebbero funzionare. Non riuscivo a farlo funzionare in questo modo qualunque metodo che ho provato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top