Access to errno from Python? Access to errno from Python? python python

Access to errno from Python?


Here is a snippet of code that allows to access errno:

from ctypes import *libc = CDLL("libc.so.6")get_errno_loc = libc.__errno_locationget_errno_loc.restype = POINTER(c_int)def errcheck(ret, func, args):    if ret == -1:        e = get_errno_loc()[0]        raise OSError(e)    return retcopen = libc.opencopen.errcheck = errcheckprint copen("nosuchfile", 0)

The important thing is that you check errno as soon as possible after your function call, otherwise it may already be overwritten.


Update: On Python 2.6+, use ctypes.get_errno().

Python 2.5

Belowed code is not reliable (or comprehensive, there are a plefora of ways errno could be defined) but it should get you started (or reconsider your position on a tiny extension module (after all on Debian python setup.py install or easy_install should have no problem to build it)). From http://codespeak.net/pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py

if not hasattr(ctypes, 'get_errno'):    # Python 2.5 or older    if sys.platform == 'win32':        standard_c_lib._errno.restype = ctypes.POINTER(ctypes.c_int)        def _where_is_errno():            return standard_c_lib._errno()    elif sys.platform in ('linux2', 'freebsd6'):        standard_c_lib.__errno_location.restype = ctypes.POINTER(ctypes.c_int)        def _where_is_errno():            return standard_c_lib.__errno_location()    elif sys.platform in ('darwin', 'freebsd7'):        standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)        def _where_is_errno():            return standard_c_lib.__error()    ctypes.get_errno = lambda: _where_is_errno().contents.value 

Where standard_c_lib:

def get_libc_name():    if sys.platform == 'win32':        # Parses sys.version and deduces the version of the compiler        import distutils.msvccompiler        version = distutils.msvccompiler.get_build_version()        if version is None:            # This logic works with official builds of Python.            if sys.version_info < (2, 4):                clibname = 'msvcrt'            else:                clibname = 'msvcr71'        else:            if version <= 6:                clibname = 'msvcrt'            else:                clibname = 'msvcr%d' % (version * 10)        # If python was built with in debug mode        import imp        if imp.get_suffixes()[0][0] == '_d.pyd':            clibname += 'd'        return clibname+'.dll'    else:        return ctypes.util.find_library('c')# Make sure the name is determined during import, not at runtimelibc_name = get_libc_name() standard_c_lib = ctypes.cdll.LoadLibrary(get_libc_name())


It looks like you can use this patch that will provide you with ctypes.get_errno/set_errno

http://bugs.python.org/issue1798

This is the patch that was actually applied to the repository:

http://svn.python.org/view?view=rev&revision=63977

Otherwise, adding a new C module that does nothing but return errno /is/ disgusting, but so is the library that you're using. I would do that in preference to patching python myself.