Pergunta

PyObject* PyImport_ImportModule( const char *nome)

Como especificar um caminho de arquivo completo e um nome de módulo?

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

Obrigado, Elias

Foi útil?

Solução 4

Eventualmente, acabei usando o load_source do módulo IMP:

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

Eu acho que é a solução mais viável. Outras sugestões são bem -vindas.

Outras dicas

Outra solução para os casos em que todo o arquivo *.py está em um diretório:

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

Não posso te dar uma resposta completa, mas acho que posso lhe dar um lugar para começar. O Python fornece um módulo interno chamado imp que fornece acesso a importar internos. Ele inclui uma função load_module () que permite passar em um caminho. Isso é implementado em Python/import.c; Basta procurar imp_load_module.

Conforme apontado, usando a solução acima do Alexp, você não pode importar módulos fora do diretório especificado. No entanto, em vez de contexto o caminho, você pode adicionar um caminho, que deve ser pesquisado por módulos. Isso pode ser feito anexando esse caminho para sys.path. Infelizmente, a API C não expõe uma função capaz de fazer isso diretamente. Em vez disso, você pode pedir ao próprio Python para fazer isso, usando

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

ou qualquer equivalente como: (Aviso: Unseded)

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

Agora você pode importar qualquer arquivo <insert folder path>/<file>.py usando o habitual

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

Para se referir ao diretório atual, basta usar "." como o caminho da pasta.

CPython irá Não hesite ligar através do imp módulo para realizar trabalhos de importação, então não há razão para que você não deva fazer isso sozinho.

Aqui está uma maneira de fazer isso em C++, onde modulePath e moduleName são variáveis ​​separadas por causa da preguiça:

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

Eu escrevi isso baseado em um dos carregadores de módulo Python dos meus projetos, que usa um gerenciamento de refcount mais sofisticado, e eu não tentei este, então use por sua conta e risco.

Eu verifiquei se a alternativa de Stesim funciona.

Não importa qual solução seja usada, é importante mencionar que, no Windows, é importante ter o caminho completo com barras em vez de barris.

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

Em algumas outras perguntas e respostas (como Windows Path in Python) afirma -se que a primeira variante também deve funcionar. Eu não conseguia fazer funcionar dessa maneira qualquer método que eu tentei.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top