[Libvir] Python bindings, errors & exceptions
Daniel P. Berrange
berrange at redhat.com
Fri Mar 23 12:58:04 UTC 2007
On Fri, Mar 23, 2007 at 12:12:56PM +0000, Richard W.M. Jones wrote:
> I'm really confused about how the Python bindings are supposed to handle
> errors. Can someone explain how this is supposed to work?
>
> Case in point: currently virt-manager fails because conn.listNetworks ()
> returns None, whereas virt-manager is expecting it to return a list of
> network objects. The code returns None because the underlying calls
> (either virConnectNumOfNetworks or virConnectListNetworks) is failing.
>
> The functions in question are:
>
> class virConnect: # libvirtclass.py
> # ...
> def listNetworks(self):
> """list the networks, stores the pointers to the names in
> @names """
> ret = libvirtmod.virConnectListNetworks(self._o)
> return ret
>
> (the above code is automatically generated by generator.py), and:
>
> static PyObject * // libvir.c
> libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED,
> PyObject *args) {
> PyObject *py_retval;
> char **names = NULL;
> int c_retval, i;
> virConnectPtr conn;
> PyObject *pyobj_conn;
>
> // ...
>
> c_retval = virConnectNumOfNetworks(conn);
> if (c_retval < 0) {
> Py_INCREF(Py_None);
> return (Py_None);
> }
>
> // ...
>
> py_retval = PyList_New(c_retval);
>
> if (names) {
> for (i = 0;i < c_retval;i++) {
> PyList_SetItem(py_retval, i,
> libvirt_constcharPtrWrap(names[i]));
> free(names[i]);
> }
> free(names);
> }
>
> return(py_retval);
> }
>
> (I've omitted some code to make the general idea clearer).
>
> The upshot is that if the underlying functions fail, at no point is an
> exception thrown.
Yes, returning None here is totally bogus - it should be raising a
libvirtError object.
> This is not always the case. For other functions which return C
> structure pointers (eg. libvirt.open which wraps virConnectOpen), the
> bindings automatically catch the invalid return and throw an exception.
> For example:
>
> def open(name): # libvirtclass.py
> """This function should be called first to get a connection to
> the Hypervisor and xen store """
> ret = libvirtmod.virConnectOpen(name)
> if ret is None:raise libvirtError('virConnectOpen() failed')
> return virConnect(_obj=ret)
>
> It is my view that all errors in C code should turn into Python exceptions.
Indeed they should - all the generated C code bindings do - its just a few
of these hand written bindings that are wrong.
> One way to do that would be to have a Python virterror handler which
> just directly throws the exception. I don't know if this is safe
> because the exception would unwind through C code, and in some languages
> that is safe, in others it is not.
I can't see that being remotely safe to do in python.
> Another way would be to have a Python virterror handler which remembers
> that an exception happened, and after each auto-generated function call
> we check this and raise the exception. Since I'm just starting out in
> Python, I don't know if there are thread or other issues with this.
That shouldn't be neccessary - the libvirtError() constructor calls the
virGetLastError or virConnectGetLastError functions to retrieve the full
error report details. So simply raise libvirtError("blah", conn) should
do the trick.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
More information about the libvir-list
mailing list