Python c-api and reusing python-objects: works only once

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • karye2004@gmail.com

    #1

    Python c-api and reusing python-objects: works only once

    Hi!

    I'm trying to access python objects from c++. It works once. Second
    time it hangs.
    Does someone have any clue or some example code or pointer?

    Thanks!
    /Karim

    Here are some python classes:

    --------------------------------------------------------------------------------------------------
    import portage

    class PortageInterfac e:
    def __init__(self):
    self.vartree = portage.db[portage.root]["vartree"]
    self.porttree = portage.db[portage.root]["porttree"]

    def installedPackag es(self):
    return self.vartree.db api.cp_all()

    def installedPackag esVersion(self) :
    t = []
    for cpv in self.vartree.db api.cpv_all():
    mysplit = portage.catpkgs plit(cpv)
    mypkg = "/".join(mysp lit[:3])
    if mysplit[3] != "r0":
    mypkg = mypkg + "-" + mysplit[3]
    t.append( mypkg )
    return t

    def portagePackages (self):
    return self.porttree.d bapi.cp_all()

    def allPortagePacka ges(self):
    t = []
    t = self.porttree.d bapi.cp_all()
    t += self.vartree.db api.cp_all()
    return t

    def allPackagesVers ion(self):
    t = []
    for x in self.porttree.d bapi.cp_all():
    t.extend( self.porttree.d bapi.cp_list(x) )
    return t

    def getAllPackageDa ta(self, db, keys):
    rval = {}
    cplist = db.cp_all()
    cplist.sort()
    for cp in cplist:
    for cpv in db.cp_list(cp):
    rval[cpv] = db.aux_get(cpv, keys)
    return rval

    def allPackagesData (self):
    testdata = {}
    testdata = self.getAllPack ageData(self.po rttree.dbapi,
    ["DESCRIPTIO N", "HOMEPAGE", "LICENSE", "KEYWORDS", "IUSE", "SLOT"])
    t = []
    for cpv in testdata.keys() :
    mysplit = portage.catpkgs plit(cpv)
    mypkg = "/".join(mysp lit[:3])
    if mysplit[3] != "r0":
    mypkg = mypkg + "-" + mysplit[3]
    t.append( mypkg )
    for v in testdata[cpv]:
    t.append( v )
    return t
    --------------------------------------------------------------------------------------------------

    And the c++ class executed inside a thread:
    --------------------------------------------------------------------------------------------------
    #include "pythonizer .h"

    #ifdef _XOPEN_SOURCE
    #undef _XOPEN_SOURCE
    #endif

    #ifdef _POSIX_C_SOURCE
    #undef _POSIX_C_SOURCE
    #endif

    #include <Python.h>

    #include <qstringlist. h>
    #include <qfile.h>

    #include <kdebug.h>

    #define foreach( x ) \
    for( QStringList::Co nstIterator it = x.begin(), end = x.end(); it !=
    end; ++it )

    #define LINE_INFO " ( " << k_funcinfo << "Line: " << __LINE__ << " )"
    << endl
    #define DEBUG_LINE_INFO kdDebug() << LINE_INFO

    Pythonizer::Pyt honizer( const char *file, char *pyClass )
    : m_file( file ), m_pyClass( pyClass )
    {
    kdDebug() << "Pythonizer::Py thonizer" << endl;
    }

    Pythonizer::~Py thonizer()
    {
    kdDebug() << "Pythonizer::~P ythonizer" << endl;
    }

    QStringList Pythonizer::get Packages( char *pyModule )
    {
    DEBUG_LINE_INFO ;

    // Initialize the Python Interpreter
    Py_Initialize() ;

    PyObject *pName, *pModule, *pDict, *pValue, *pClass, *pInstance;

    // Build the name object
    pName = PyString_FromSt ring( m_file );

    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    // Load the module object
    pModule = PyImport_Import ( pName );

    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    // pDict is a borrowed reference
    pDict = PyModule_GetDic t( pModule );

    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    // Build the name of a callable class
    pClass = PyDict_GetItemS tring( pDict, m_pyClass );

    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    // Create an instance of the class
    if ( PyCallable_Chec k( pClass ) ) {
    pInstance = PyObject_CallOb ject( pClass, NULL );

    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }
    }
    else {
    kdDebug() << "Can not create python class instance." << endl;
    return QStringList::QS tringList();
    }

    // Call a method of the class with two parameters
    pValue = PyObject_CallMe thod( pInstance, pyModule, NULL );

    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    PyObject *iterator = PyObject_GetIte r( pValue );
    if ( iterator == NULL ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }

    QStringList packageList;
    PyObject *item;
    while ( item = PyIter_Next( iterator ) ) {
    packageList << PyString_AsStri ng( item );

    /* release reference when done */
    Py_DECREF( item );
    }
    Py_DECREF( iterator );

    // Clean up
    Py_DECREF( pValue );
    Py_DECREF( pInstance );
    Py_DECREF( pClass );
    // Py_DECREF( pDict );
    Py_DECREF( pModule );
    Py_DECREF( pName );

    PyErr_Clear();

    DEBUG_LINE_INFO ;

    // Finish the Python Interpreter
    Py_Finalize();

    return packageList;
    }
    --------------------------------------------------------------------------------------------------

    --------------------------------------------------------------------------------------------------
    #ifndef PYTHONIZER_H
    #define PYTHONIZER_H

    #include <qstringlist. h>

    class Pythonizer{
    public:
    Pythonizer( const char *file, char *pyClass );
    ~Pythonizer();

    QStringList getPackages( char *pyModule );

    private:
    QString m_file;
    QString m_pyClass;
    };

    #endif
    --------------------------------------------------------------------------------------------------

  • Gabriel Genellina

    #2
    Re: Python c-api and reusing python-objects: works only once

    At Wednesday 8/11/2006 17:04, karye2004@gmail .com wrote:
    >I'm trying to access python objects from c++. It works once. Second
    >time it hangs.
    >Does someone have any clue or some example code or pointer?
    In general, try to make a *small* example that reproduces the problem you have.
    >And the c++ class executed inside a thread:
    >--------------------------------------------------------------------------------------------------
    >QStringList Pythonizer::get Packages( char *pyModule )
    >{
    // Initialize the Python Interpreter
    Py_Initialize() ;
    >
    [... some code ...]
    >
    DEBUG_LINE_INFO ;
    if ( PyErr_Occurred( ) ) {
    PyErr_Print();
    PyErr_Clear();
    return QStringList::QS tringList();
    }
    >
    [... more code ...]
    // Finish the Python Interpreter
    Py_Finalize();
    >
    return packageList;
    >}
    You are initializing the interpreter on *each* call to getPackages -
    don't do that. Worse, "inside a thread". Just initialize the
    interpreter when your program begins, and finalize it when your program ends.
    Your current code does not call Py_Finalize when an error occurs. The
    next time, you invoke Py_Initialize again; and you shouldn't.


    --
    Gabriel Genellina
    Softlab SRL

    _______________ _______________ _______________ _____
    Correo Yahoo!
    Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
    ¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar

    Comment

    Working...