2011-11-03 8 views
5

ejemplo canónico de un programa extending embedded Python 3.x en C/C++:¿Hace PyImport_ImportModule e importa la instrucción de carga en diferentes espacios de nombres? Aquí es

#include <Python.h> 
//// Definition of 'emb' Python module //////////////////// 
static PyObject* emb_foo(PyObject *self, PyObject *args) 
{ 
    char const* n = "I am foo"; 
    return Py_BuildValue("s", n); 
} 
static PyMethodDef EmbMethods[] = { 
    {"foo", emb_foo, METH_VARARGS, "Returns foo"}, 
    {NULL, NULL, 0, NULL} 
}; 
static PyModuleDef EmbModule = { 
    PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods, 
    NULL, NULL, NULL, NULL 
}; 
static PyObject* PyInit_emb(void) 
{ 
    return PyModule_Create(&EmbModule); 
} 
//// Embedded Python with 'emb' loaded //////////////////// 
int main() 
{ 
    PyImport_AppendInittab("emb", &PyInit_emb); 
    Py_Initialize(); 

    PyRun_SimpleString("import emb\n");  // (1) 
    //PyImport_ImportModule("emb");   // (2) 

    PyRun_SimpleString("print(emb.foo())\n"); // (3) 

    Py_Finalize(); 
    return 0; 
} 

agrego el módulo emb de muebles empotrados del intérprete embebido. También me gustaría importarlo automáticamente, para que los usuarios no tengan que emitir la declaración import emb en sus scripts provistos a mi intérprete incorporado. Estoy intentando dos formas de importar, en las líneas (1) y (2).

El (1) obras y el módulo emb se pueden encontrar sin importar explícita en la simple prueba en línea (3). Sin embargo, si comento hacia fuera de la línea de (1) y elimine la línea (2) importar con C API de Python 3 llamada, entonces la línea (3) produce error:

Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
NameError: name 'emb' is not defined 

Me gustaría entender cuál es la diferencia entre las dos maneras de importar. ¿Importan módulos en diferentes namespaces/scopes?

El Python 3 documentación me llevó a lo largo de este camino:

  1. PyImport_ImportModule se describe mejor haciendo referencia a la función integrada en función de Python __import__()
  2. __import__() es invocada por la declaración de importación.

Tal vez he cometido un error asumir PyImport_ImportModule es uno-a-uno equivalente y que debería usar PyImport_ImportModuleEx con correcta (que es exactamente?) Globales y locales, así que mis tierras 'emb' en espacio de nombres global de mi intérprete embebido .

Respuesta

7

__import__ no coloca el módulo en ningún espacio de nombres, pero lo devuelve en su lugar. import llamadas __import__, además de almacenar el resultado en una variable. El docs decir que import spam hace algo similar a:

spam = __import__('spam', globals(), locals(), [], 0) 

Para obtener el mismo efecto en la API de C, es necesario asignar a la emb global. En otras palabras, configure el atributo emb en el módulo __main__.

PyObject* emb_module = PyImport_ImportModule("emb"); 
PyObject* main_module = PyImport_AddModule("__main__"); 
PyObject_SetAttrString(main_module, "emb", emb_module); 
Py_XDECREF(emb_module); 
/* (main_module is a borrowed reference) */ 
+0

+1 ¡Trabajos! Veo dónde estaba mi malentendido. Si no se ha probado el código, solo "emb" necesita ser envuelto con PyUnicode_FromString ("emb"). También noté que hay un atajo para obtener __main__: PyObject * main_module = PyImport_AddModule ("__ main__"); – mloskot

+1

Editado, gracias. Usé 'PyObject_SetAttrString' en lugar de' PyUnicode_FromString' (más corto, menos preocupante sobre la administración de referencias). –

+0

Creo que el valor de retorno de PyImport_AddModule es una referencia prestada, por lo que no debería estar decretándolo. –

Cuestiones relacionadas