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

K

karye2004

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 PortageInterface:
def __init__(self):
self.vartree = portage.db[portage.root]["vartree"]
self.porttree = portage.db[portage.root]["porttree"]

def installedPackages(self):
return self.vartree.dbapi.cp_all()

def installedPackagesVersion(self):
t = []
for cpv in self.vartree.dbapi.cpv_all():
mysplit = portage.catpkgsplit(cpv)
mypkg = "/".join(mysplit[:3])
if mysplit[3] != "r0":
mypkg = mypkg + "-" + mysplit[3]
t.append( mypkg )
return t

def portagePackages(self):
return self.porttree.dbapi.cp_all()

def allPortagePackages(self):
t = []
t = self.porttree.dbapi.cp_all()
t += self.vartree.dbapi.cp_all()
return t

def allPackagesVersion(self):
t = []
for x in self.porttree.dbapi.cp_all():
t.extend( self.porttree.dbapi.cp_list(x) )
return t

def getAllPackageData(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.getAllPackageData(self.porttree.dbapi,
["DESCRIPTION", "HOMEPAGE", "LICENSE", "KEYWORDS", "IUSE", "SLOT"])
t = []
for cpv in testdata.keys():
mysplit = portage.catpkgsplit(cpv)
mypkg = "/".join(mysplit[: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::ConstIterator 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::pythonizer( const char *file, char *pyClass )
: m_file( file ), m_pyClass( pyClass )
{
kdDebug() << "Pythonizer::pythonizer" << endl;
}

Pythonizer::~Pythonizer()
{
kdDebug() << "Pythonizer::~Pythonizer" << endl;
}

QStringList Pythonizer::getPackages( char *pyModule )
{
DEBUG_LINE_INFO;

// Initialize the Python Interpreter
Py_Initialize();

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

// Build the name object
pName = PyString_FromString( m_file );

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

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

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

// pDict is a borrowed reference
pDict = PyModule_GetDict( pModule );

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

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

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

// Create an instance of the class
if ( PyCallable_Check( pClass ) ) {
pInstance = PyObject_CallObject( pClass, NULL );

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

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

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

PyObject *iterator = PyObject_GetIter( pValue );
if ( iterator == NULL ) {
PyErr_Print();
PyErr_Clear();
return QStringList::QStringList();
}

QStringList packageList;
PyObject *item;
while ( item = PyIter_Next( iterator ) ) {
packageList << PyString_AsString( 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
--------------------------------------------------------------------------------------------------
 
G

Gabriel Genellina

At said:
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::getPackages( char *pyModule )
{
// Initialize the Python Interpreter
Py_Initialize();

[... some code ...]

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

[... 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top