A dir() function with filtering options

Updated Gribouillis 2 Tallied Votes 486 Views Share

This snippet defines a dir() function which extends python's builtin dir() function by adding options to filter the returned sequence of strings by the means of regular expressions. The main use case is live inspection of python objects and modules during an interactive session with the python interpreter.

The idea of such a function is not new. I remember having met similar functions in old modules by well known python gurus, Reddite Caesari quae sunt Caesaris !

#!/usr/bin/env python
# -*-coding: utf8-*-
# Title: diroption.py
# Author: Gribouillis for the python forum at www.daniweb.com
# Created: 2012-10-10 10:46:31.935882 (isoformat date)
# License: Public Domain
# Use this code freely.

import __builtin__
import inspect, re
from itertools import ifilter, ifilterfalse

def dir(*args, **kwd):
    """Like builtin dir() function with added filtering options.
    
    synopsis:
        dir([object], [regex=string(s)], [exclude=string(s)])
    
    The Optional keyword arguments are 'regex' and 'exclude',
    which values can be a string, or a sequence of strings, satisfying
    the syntax of python's regular expression.
    
    Names returned by the builtin function dir() are filtered
    to only those names containing the specified regex, or
    not containing the regex in the case of the exclude keyword.
    
    Example:

        >>> import socket
        >>> dir(socket, regex = "(?i)host") # list names containing 'host', case insensitive.
        ['AI_NUMERICHOST', 'INADDR_ALLHOSTS_GROUP', ..., 'gethostbyname_ex', 'gethostname']
        >>> 
        >>> dir(socket, regex = "(?i)host", exclude = "I") # same list, but exclude names containing I
        ['PACKET_HOST', 'PACKET_OTHERHOST', 'gethostbyaddr', 'gethostbyname', 'gethostbyname_ex', 'gethostname']
        >>> dir(socket, regex = "(?i)host", exclude = ("I", "PAC")) # regex and exclude can be iterables
        ['gethostbyaddr', 'gethostbyname', 'gethostbyname_ex', 'gethostname']

    """
    if len(args) > 1:
        raise TypeError("dir expected at most 1 positional argument, got %s" % len(args))
    badkwd = [k for k in kwd if k not in ("regex", "exclude")]
    if len(badkwd):
        raise TypeError("dir got an unexpected keyword argument '%s'" % badkwd[0])
    if len(args):
        names = __builtin__.dir(args[0])
    else:
        names = list(inspect.currentframe().f_back.f_locals.keys())
    for key, fil in (("regex", ifilter), ("exclude", ifilterfalse)):
        regex = kwd.get(key, None)
        if regex is not None and not isinstance(regex, basestring):
            regex = "|".join(regex)
        if regex:
            names = fil(re.compile(regex).search, names)
    return list(names)
Gribouillis 1,391 Programming Explorer Team Colleague

Using the same principle, one can also modify the vars() function to return a partial dictionary for use in an interactive session

import __builtin__
import inspect, re
from itertools import ifilter, ifilterfalse


def vars(*args, **kwd):

    if len(args) > 1:
        raise TypeError("vars expected at most 1 positional argument, got %s" % len(args))
    badkwd = [k for k in kwd if k not in ("regex", "exclude")]
    if len(badkwd):
        raise TypeError("vars got an unexpected keyword argument '%s'" % badkwd[0])
    if len(args):
        dic = __builtin__.vars(args[0])
    else:
        dic = list(inspect.currentframe().f_back.f_locals)
    names = dic.iterkeys()
    for key, fil in (("regex", ifilter), ("exclude", ifilterfalse)):
        regex = kwd.get(key, None)
        if regex is not None and not isinstance(regex, basestring):
            regex = "|".join(regex)
        if regex:
            names = fil(re.compile(regex).search, names)
    return dict((k, dic[k]) for k in names)

if __name__ == "__main__":
    import os
    print(vars(os, regex="fd"))
    # prints {'fdopen': <built-in function fdopen>, 'fdatasync': <built-in function fdatasync>}

Notice that a new dictionary is created (contrary to the built in vars())

TrustyTony 888 pyMod Team Colleague Featured Poster

Here for comparison how you could do without the first code snippet the examples given and without re module.

>>> import socket
>>> [s for s in dir(socket) if 'host' in s.lower()]
['AI_NUMERICHOST', 'INADDR_ALLHOSTS_GROUP', 'NI_MAXHOST', 'NI_NUMERICHOST', 'gethostbyaddr', 'gethostbyname', 'gethostbyname_ex', 'gethostname']
>>> [s for s in dir(socket) if 'host' in s.lower() and 'I' not in s]
['gethostbyaddr', 'gethostbyname', 'gethostbyname_ex', 'gethostname']
>>> [s for s in dir(socket) if 'host' in s.lower() and all(exclude not in s
                               for exclude in ('I', 'PAC'))]
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.