Access to Errno from Python

Access to errno from Python?

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 runtime
libc_name = get_libc_name()
standard_c_lib = ctypes.cdll.LoadLibrary(get_libc_name())

How can I access errno from Python's CFFI?

See docs https://cffi.readthedocs.org/en/release-0.6/

ffi.errno is a property of the cffi.FFI object.

e.g.

from cffi import FFI    
ffi = FFI()
# error happens
print ffi.errno

ffi.errno: the value of errno received from the most recent C call in this thread, and passed to the following C call, is available via reads and writes of the property ffi.errno. On Windows we also save and restore the GetLastError() value, but to access it you need to declare and call the GetLastError() function as usual.

How to get an error message for errno value in python?

This prints ENODEV: No such device.

import errno, os

def error_text(errnumber):
return '%s: %s' % (errno.errorcode[errnumber], os.strerror(errnumber))

print error_text(errno.ENODEV)

Getting errno after an error in wrapped c function in Python

You have to get errno from the same CRT library that Python was built with. So for Python 3.7 on Windows. I don't have Linux handy to try, so hopefully this puts you in the right direction.

>>> dll = CDLL('ucrtbase',use_errno=True)
>>> get_errno()
0
>>> dll._access(b'nonexisting',0)
-1
>>> get_errno()
2

Errno 2 is ENOENT (No such file or directory) so it got set and looks correct.

A different CRT library has a different errno instance so it isn't captured correctly by Python for use with set_errno()/get_errno().

Python [Errno 21] Is a directory when trying access USB device [/dev/bus/usb/001/001] on embedded Linux device

By digging around a little bit, I determined that the ioctl number 21780 that you are sending to the kernel is known as USBDEVFS_RESET in the kernel. (If you already knew that, it would have been really good info to include in your question.)

Using elixir.bootlin.com, I was able to track down the code that runs in the Linux kernel when you send that ioctl and look for cases that cause it to return the "is directory" error. In the usb_reset_device function in hub.c, I found this code:

    if (!udev->parent) {
/* this requires hcd-specific logic; see ohci_restart() */
dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
return -EISDIR;
}

What that code shows us if that if you attempt to reset a USB device that is actually the USB root hub (because it has no parent), that is not supported. I think you are attempting to reset the USB root hub instead of the actual device that is having trouble, and Linux is telling you that it does not know how to do that.

Note that if your USB device is in the Default state as defined by the USB specification then it has not yet been assigned an address and it is just using address 0. So we wouldn't expect either of the two devices in your lsusb output to correspond to that device, because they have addresses 1 and 2.

I think maybe what you are looking for is a way to talk to whatever hub your device is connected to and tell it to reset the appropriate port. I don't think you can really talk to the device if Linux is so confused about it that it got stuck in the default state.

Availability of errno module in python across different platforms

errno is available since Python 1.4. The availability of the names such as ENOENT may depend on the platform: there are tons of ifdefs in the errno module source. "errno.h" header is checked in ./configure so it might not be available everywhere (it seems it is not used on WinCE) but it shouldn't prevent import errno.

Here's the initial revision that introduces errno=None:

 try:
- from errno import EBADF
+ import errno
except ImportError:
- EBADF = 9
+ errno = None
+EBADF = getattr(errno, 'EBADF', 9)
+EINTR = getattr(errno, 'EINTR', 4)

I can understand the state before: from errno import EBADF may raise ImportError because EBADF might not be available on the system. The state after, I don't understand. I think import errno should be always successful on CPython on any platform.



Related Topics



Leave a reply



Submit