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

karye2004 at gmail.com karye2004 at gmail.com
Wed Nov 8 15:04:02 EST 2006


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




More information about the Python-list mailing list