2011-11-03 6 views
5

Ecco esempio canonico di un programma extending embedded Python 3.x in C/C++:Do PyImport_ImportModulo e importazione vengono caricati in spazi dei nomi diversi?

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

aggiungo il modulo emb a built-in dell'interprete incorporato. Vorrei anche importarlo automaticamente, in modo che gli utenti non debbano rilasciare la dichiarazione import emb negli script forniti all'interprete incorporato. Sto provando due modi di importazione, nelle righe (1) e (2).

Il (1) opere e il modulo emb possono essere trovati senza importazione esplicito nel semplice test in linea (3). Tuttavia, se commento fuori linea (1) e rimuovere la linea (2) importare con C API di Python 3 chiamata, poi la linea (3) produce errore:

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

Mi piacerebbe capire qual è la differenza qui tra i due modi di importare. Importano il modulo in diversi namespaces/scopes?

Il Python 3 documentazione mi ha portato in questo cammino:

  1. PyImport_ImportModule è meglio descritta facendo riferimento alla funzione __import__()
  2. __import__() funzione built-in Python viene invocato dalla dichiarazione di importazione.

Forse ho commesso un errore assumendo PyImport_ImportModule è uno-a-uno equivalente e dovrebbe usare PyImport_ImportModuleEx con la corretta (che esattamente?) Globali e locali, così le mie terre 'emb' nel namespace globale del mio interprete incorporato .

risposta

7

__import__ non inserisce affatto il modulo in alcuno spazio dei nomi, ma lo restituisce. import chiama __import__ e memorizza il risultato in una variabile. Il docs dicono che import spam fa qualcosa di simile a:

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

Per ottenere lo stesso effetto nell'API C, è necessario assegnare al emb globale. In altre parole, impostare l'attributo emb sul modulo __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 Opere! Vedo dov'era il mio fraintendimento. Re codice non testato, solo "emb" deve essere avvolto con PyUnicode_FromString ("emb"). Ho anche notato che c'è un collegamento per ottenere __main__: PyObject * main_module = PyImport_AddModule ("__ main__"); – mloskot

+1

Modificato, grazie. Ho usato 'PyObject_SetAttrString' piuttosto che' PyUnicode_FromString' (più corto, meno preoccupante di gestire i riferimenti). –

+0

Penso che il valore restituito da PyImport_AddModule sia un riferimento preso a prestito, quindi non dovresti decriverlo. –