Eryk Sun <[email protected]> added the comment:
Assign an errcheck function to check the return value and raise an OSError
exception on failure. Load the C library with use_errno=True to get the value
of C errno. Make sure to properly handle encoding Unicode strings for the
file-system encoding, including conversion of __fspath__ paths (e.g. 3.x
pathlib). Finally, don't load libraries and define prototypes in API functions.
It's redundant and inefficient. You're just needlessly increasing the loaders
reference count on the shared library and needlessly redefining prototypes that
never change. Load it once at module or class level.
For example:
import os
import sys
import ctypes
import ctypes.util
import contextlib
libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
class DIR(ctypes.Structure):
"""Opaque type for directory entries"""
PDIR = ctypes.POINTER(DIR)
class c_fschar_p(ctypes.c_char_p):
if sys.version_info[0] >= 3:
@classmethod
def from_param(cls, param):
if isinstance(param, (str, bytes, os.PathLike)):
param = os.fsencode(param)
return super().from_param(param)
else:
@classmethod
def from_param(cls, param):
if isinstance(param, unicode):
param = param.encode(sys.getfilesystemencoding())
return super(c_fschar_p, cls).from_param(param)
def check_bool(result, func, args):
if not result:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return args
def check_int(result, func, args):
if result == -1:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return args
libc.opendir.errcheck = check_bool
libc.opendir.argtypes = (c_fschar_p,)
libc.opendir.restype = PDIR
libc.dirfd.errcheck = check_int
libc.dirfd.argtypes = (PDIR,)
libc.closedir.errcheck = check_int
libc.closedir.argtypes = (PDIR,)
@contextlib.contextmanager
def get_directory_file_descriptor(directory):
dir_p = libc.opendir(directory)
try:
if __debug__:
print("dir_p = %s:%r" % (directory, dir_p))
dir_fd = libc.dirfd(dir_p)
if __debug__:
print("dir_fd = %r" % dir_fd)
yield dir_fd
finally:
libc.closedir(dir_p)
if __debug__:
print("closed %r" % dir_p)
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue35180>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com