Доступ к errno из Python?

Я застрял с довольно сложным модулем Python, который не возвращает полезные коды ошибок (он действительно терпит неудачу молча). Однако основная библиотека C, которую он вызывает, устанавливает errno.

Обычно errno входит в атрибуты OSError, но поскольку у меня нет исключения, я не могу это понять.

Используя ctypes, libc.errno не работает, потому что errno является макросом в GNU libc. Python 2.6 имеет некоторые преимущества, но Debian по-прежнему использует Python 2.5. Вставка модуля C в мою чистую программу Python просто для того, чтобы читать errno, отвращает меня.

Есть ли способ доступа к errno? Решение Linux только прекрасно, поскольку обернутая библиотека – это только Linux. Мне также не нужно беспокоиться о потоках, так как я выполняю только один поток за время, в которое это может потерпеть неудачу.

6 Solutions collect form web for “Доступ к errno из Python?”

Понятый код не является надежным (или всеобъемлющим, существует множество способов определения errno ), но он должен заставить вас начать (или пересмотреть свою позицию на крошечном модуле расширения (в конце концов, на Debian python setup.py install или easy_install должно быть нет проблем с его построением)). С 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 

Где 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()) 

Вот фрагмент кода, который позволяет получить доступ к errno :

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

Важно то, что вы проверяете errno как можно скорее после вызова функции, иначе она уже может быть перезаписана.

Похоже, вы можете использовать этот патч, который предоставит вам ctypes.get_errno/set_errno

http://bugs.python.org/issue1798

Это патч, который был фактически применен к репозиторию:

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

В противном случае добавление нового модуля C, который ничего не делает, кроме возврата errno / is / disgusting, но так же, как и библиотека, которую вы используете. Я бы сделал это, предпочитая исправлять сам python.

Поднялись и проследили через заголовки C.

 import ctypes c = ctypes.CDLL("libc.so.6") c.__errno_location.restype = ctypes.POINTER(ctypes.c_int) c.write(5000, "foo", 4) print c.__errno_location().contents # -> c_long(9) 

Он не работает в командной строке python, потому что он сбрасывает errno для чтения из stdin.

Как только вы узнаете волшебное слово __errno_location, это выглядит как общий шаблон. Но с ошибкой я был довольно потерян.

Я не уверен, что это то, о чем вы и Jerub имеете в виду, но вы можете написать очень короткое расширение C, которое просто экспортирует errno, то есть с интерфейсом языка python .

В противном случае я согласен с вами в том, что добавить этот маленький бит скомпилированного кода – это боль.

ctypes на самом деле дает стандартный способ доступа к реализации cython python, который использует errno. Я не тестировал это ни на что другое, кроме моей (linux) системы, но это должно быть очень портативным:

ctypes.c_int.in_dll (ctypes.pythonapi, "ERRNO")

который возвращает c_int, содержащий текущее значение.

  • Поддержка китайского и японского символов в python
  • Окончательный ответ на относительный импорт питона
  • Как правильно использовать isinstance () для python, чтобы проверить, является ли переменная числом?
  • Как «супер» Python поступает правильно?
  • Python: избегать новой строки с командой печати
  • Могу ли я использовать Python 3 super () в Python 2.5.6?
  • Как включить и использовать .eggs / pkg_resources в каталоге проекта, ориентированном на python 2.5.1
  • Как я могу перечислить методы в модуле Python 2.5?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.