我被困在一个相当复杂的Python模块中,该模块不会返回有用的错误代码(它实际上会无声地失败而失败)。但是,它调用的基础C库设置了errno。
通常,errno是通过OSError属性传入的,但是由于我没有异常,因此无法理解。
使用ctypes时,libc.errno不起作用,因为errno是GNU libc中的宏。Python 2.6有一些优势,但Debian仍使用Python 2.5。将C模块插入我的纯Python程序中只是为了阅读errno,这使我感到恶心。
有什么办法可以访问errno?仅Linux的解决方案很好,因为要包装的库仅Linux。我也不必担心线程,因为我只会在可能失败的时间内运行一个线程。
更新:在 Python 2.6+上 ,使用ctypes.get_errno()。
ctypes.get_errno()
下面的代码不可靠(或全面,有多种方法errno可以定义),但它应该可以帮助您入门(或重新考虑您在小型扩展模块上的位置(毕竟在Debian上,python setup.py install或者easy_install在构建它时应该没有问题)) 。来自 http://codespeak.net/pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
errno
python setup.py install
easy_install
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
哪里standard_c_lib:
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 runtime libc_name = get_libc_name() standard_c_lib = ctypes.cdll.LoadLibrary(get_libc_name())