2015-03-12 24 views
5

Sto provando a creare tramite boost python un pacchetto che includa diversi moduli.Boost python multiple modules in un oggetto condiviso

Il ragionamento è che vogliamo esporre un'API molto grande e ha senso raggrupparlo in diversi moduli per facilità d'uso e preservare l'utilizzo della memoria Python. D'altra parte siamo costretti (per motivi oltre la portata di questa domanda per compilare questo in un unico oggetto condiviso)

Così ho creare con boost pitone un pacchetto che esporta diversi moduli, come segue:

void exportClass1() 
{ 
    namespace bp = boost::python; 
    // map the IO namespace to a sub-module 
    // make "from myPackage.class1 import <whatever>" work 
    bp::object class1Module(bp::handle<>(bp::borrowed(PyImport_AddModule("myPackage.class1")))); 
    // make "from mypackage import class1" work 
    bp::scope().attr("class1") = class1Module; 
    // set the current scope to the new sub-module 
    bp::scope io_scope = class1Module; 

    // export stuff in the class1 namespace 

    class_<class1 >("class1", init<>()) 
    . 
    . CLASS SPECIFICS GO HERE 
    . 

    Other class of module class1 go here as well 
} 

BOOST_PYTHON_MODULE(myPackage) 
{ 
    namespace bp = boost::python; 

    // specify that this module is actually a package 
    bp::object package = bp::scope(); 
    package.attr("__path__") = "myPackage"; 

    exportClass1(); 
    exportClass2(); 
    . 
    . 
    . 

} 

Questo codice funziona.

Il problema principale è il consumo di memoria. L'api esposta complessiva è molto grande quindi il caricamento dell'intero pacchetto consuma circa 65 MB di ram, solo per tutte le dichiarazioni. (prima che l'utente del pacchetto iniziasse a fare qualcosa)

Questo è ovviamente inaccettabile. (Dato che il caricamento di un singolo modulo dovrebbe consumare magari 1-3MB di RAM)

Quando in pitone, se chiamo:

from myPackage.myModule import * 

O

from myPackage.myModule import someClass 

Il consumo di memoria skyrockets immidietly a 65 MB .

Dopo aver fatto nessuna delle importazioni se chiamo: sys.modules vedo tutte le classi nel mio pacchetto come "noto" Tuttavia se corro:

from myPackage.myModule import class1 
c = class2() 

ottengo un errore:

NameError: name 'class2' is not defined

Così sembra ottengo il peggiore dei due mondi, da un mani consumare memoria come se ho importato tutto dal mio pacchetto, d'altra parte non ho ricevuto le classi effettivamente importati.

Qualche idea su come risolvere questo problema, in modo tale che importando un modulo specifico verrà importato e non tutti i dati del pacchetto verranno letti nella memoria python. (che richiede tempo e consuma molta memoria preziosa)

risposta

2

Quindi questo era molto più semplice di quanto pensassi.

Il codice sopra è corretto anche per fare le chiamate in forma di:

from myPackage.myModule import class1 
c = class2() 

Nei impediva questo venga eseguito correttamente erano i percorsi di sistema. L'oggetto condiviso non è stato posizionato in una posizione del percorso Python e non ha avuto un __init__.py nella cartella in cui è stato inserito.

Non appena l'oggetto condiviso è stato inserito nella cartella dei pacchetti di sito corretta, che, naturalmente, ha __init__.py, l'esempio sopra funziona correttamente.