Looking for os.listdir() generator

Nick Craig-Wood nick at craig-wood.com
Thu Jul 23 16:29:57 EDT 2009


Christian Heimes <lists at cheimes.de> wrote:
>  I'm looking for a generator version of os.listdir() for Python 2.5 and
>  newer. I know somebody has worked on it because I've seen a generator
>  version in a posting on some list or blog a while ago. I can't find it
>  anymore. It seems my Google fu is lacking today. All I can find is a
>  very old version of xlistdir. A Cython based solution is appreciated but
>  please no ctypes version.

I posted exactly that yesterday I think ;-)

Note that this has a python part as well as a ctypes part because the
version of ctypes I used doesn't support generators.  I think the
development version does though.

Here is it

--setup.py----------------------------------------------------------

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("directory", ["directory.pyx"])]
)

--directory.pyx----------------------------------------------------------

# Cython interface for listdir
# python setup.py build_ext --inplace

import cython

cdef extern from "dirent.h":
    struct dirent:
        char d_name[0]
    ctypedef struct DIR
    DIR *opendir(char *name)
    int closedir(DIR *dirp)
    dirent *readdir(DIR *dirp)

cdef extern from "errno.h":
    int errno

cdef extern from "string.h":
    char *strerror(int errnum)

cdef class Directory:
    """Represents an open directory"""
    
    cdef DIR *handle

    def __init__(self, path):
        self.handle = opendir(path)
        if self.handle is NULL:
            raise OSError(errno, "Failed to open directory: %s" % strerror(errno))

    def readdir(self):
        """Read the next name in the directory"""
        cdef dirent *p
        p = readdir(self.handle)
        if p is NULL:
            return None
        return p.d_name

    def close(self):
        """Close the directory"""
        if self.handle is not NULL:
            closedir(self.handle)
            self.handle = NULL

    def __dealloc__(self):
        self.close()

--listdir.py----------------------------------------------------------

from directory import Directory

def listdir(path):
    """
    A generator to return the names of files in the directory passed in
    """
    d = Directory(path)
    while True:
        name = d.readdir()
        if not name:
            break
        if name not in (".", ".."):
            yield name
    d.close()
    del d

if __name__ == "__main__":
    import sys
    paths = sys.argv[1:]
    if not paths:
        paths = ["."]
    for path in paths:
        print "*** %s ***" % path
        for name in listdir(path):
            print name

------------------------------------------------------------

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list