VMware ESXi and vSphere Cluster Management

How to Display and Inspect Python Module Contents with dir()

Learn how to import a Python module, list its functions and attributes with dir(), inspect module metadata, use help() and getattr(), and recognize public API conventions.

What Is a Python Module?

A module is an importable unit of Python code. Usually, it is a .py file, although Python can also load modules from packages, compiled code, built-in implementations, or other importable sources.

A module can provide functions, classes, variables, constants, and metadata. When you import a module, Python creates a module object and binds it to a name in your program. You can then access its contents with dot notation, such as module_name.function_name.

An attribute is a named value accessed through an object. For example, math.pi accesses the pi attribute of the math module.

Create and Import a Small Module

Create a file named simple_module.py with this content:

"""Small examples for module inspection."""

GREETING = "Hello"


def welcome(name="Python"):
    """Return a welcome message."""
    return f"{GREETING}, {name}!"


def bye(name="Python"):
    """Return a farewell message."""
    return f"Goodbye, {name}!"

In another Python file, or in the interactive interpreter started in the same directory, import the module:

import simple_module

The module name, simple_module, is the value you pass to inspection tools such as dir() and help().

Use dir() to Display Module Contents

dir() is a built-in function for introspection, which means examining objects while a program is running. Given a module, dir(module_name) returns a list of attribute names accessible on that module.

names = dir(simple_module)
print(names)

The result is a list of strings. You can display it, store it, sort it, or filter it:

print(dir(simple_module))

public_names = [
    name for name in dir(simple_module)
    if not name.startswith("_")
]
print(public_names)

The filtered result should include names such as GREETING, welcome, and bye. The complete result will usually contain additional names beginning and ending with double underscores.

dir() is useful when exploring an unfamiliar API, working in the interactive interpreter, debugging, or learning which names a module exposes. It does not mean that every returned name was manually written in the module source.

How to Read dir() Output

Normal names can represent functions, classes, constants, or other module-level variables. In the example, welcome and bye are user-defined functions, while GREETING is a module-level variable commonly treated as a constant by naming convention.

Names surrounded by double underscores, such as __name__, are called dunder attributes. “Dunder” is short for “double underscore.” These names provide metadata or support Python's runtime, object, and import mechanisms.

A module's directory can therefore contain both names defined by the author and names supplied or maintained by Python. The presence of a name in dir() does not automatically make it part of the module's intended public API.

Common Module Special Attributes

AttributeTypical purposeAvailability and notes

__doc__ — The module's documentation string, taken from a leading string literal when one exists. It can be None if no module docstring is present.

__file__ — The source or loaded-file path for a file-based module. It is not guaranteed for built-in, frozen, dynamically created, or otherwise special modules.

__name__ — The name assigned to the module, such as simple_module. A package module can have a dotted name.

__package__ — Package-context metadata used by the import system, especially when resolving relative imports.

__spec__ — The import specification object describing how the module was found and loaded.

__loader__ — The loader object or loader-related information associated with loading the module, where applicable.

__cached__ — The path to a cached bytecode file when Python provides one. It may be absent or unavailable.

__builtins__ — A reference related to built-in names available in the module namespace. Its representation can vary; it may be a module or a dictionary.

You can inspect these values directly:

print(simple_module.__doc__)
print(simple_module.__name__)
print(simple_module.__package__)
print(simple_module.__spec__)
print(simple_module.__loader__)

# These may not exist for every module:
print(getattr(simple_module, "__file__", None))
print(getattr(simple_module, "__cached__", None))

Inspect a Function from a Module

dir() works on individual objects as well as modules. Select a function with dot notation and pass it to dir():

print(dir(simple_module.bye))

The output can include function-related attributes such as:

  • __name__: the function's name, such as bye.
  • __doc__: the function's documentation string.
  • __module__: the module where the function was defined.
  • __annotations__: a dictionary of annotations, if annotations were written.
  • __defaults__: default positional argument values, such as ("Python",) for this example.
  • __code__: the function's code object.
  • __qualname__: the function's qualified name.

A function also has many dunder attributes related to Python's object and callable behavior. These are not additional farewell functions implemented by simple_module; they are attributes of the function object itself.

Access Listed Attributes Directly

Finding a name with dir() does not invoke or read it. Use the appropriate syntax to access the value.

To call a listed function, use the module name, a dot, the function name, and parentheses:

message = simple_module.welcome("Ada")
print(message)

print(simple_module.bye())

The expression simple_module.welcome retrieves the function object. Adding ("Ada") calls that function with an argument.

To read a listed module variable, use dot notation without parentheses:

print(simple_module.GREETING)

Remember that a listed attribute is not necessarily intended for external callers. Public API design is communicated by documentation, naming conventions, and sometimes __all__.

Compare dir() with Other Inspection Tools

Tool or techniqueBest useWhat it returns or displaysExample target

dir() — Quickly discover names on an object — A list of attribute-name strings — dir(simple_module)

help() — Read documentation-oriented information — Formatted help text including docstrings and signatures when available — help(simple_module)

getattr() — Retrieve an attribute when its name is stored in a variable — The attribute's value, or a supplied fallback — getattr(simple_module, "bye")

inspect — Perform deeper programmatic introspection — Standard-library functions and objects for signatures, source information, and other details — inspect.signature(simple_module.bye)

__doc__ — Read documentation directly — A string or Nonesimple_module.__doc__

Use dir() when you need a name list. Use help() when you need an explanation of how an API is documented:

help(simple_module)
help(simple_module.bye)

You can read a module docstring directly:

print(simple_module.__doc__)

getattr() is useful when the attribute name is data rather than a literal in your source:

attribute_name = "bye"
function_object = getattr(simple_module, attribute_name)
print(function_object("Sam"))

For deeper inspection, import the standard-library inspect module. It is useful for tasks such as examining a callable's signature, but dir() remains the simplest exploration tool:

import inspect

print(inspect.signature(simple_module.bye))

Explore a Standard-Library Module

You can inspect an installed module without creating a local file. For example:

import math

print(dir(math))

public_math_names = [
    name for name in dir(math)
    if not name.startswith("_")
]
print(public_math_names)

The filtered list emphasizes likely public names such as cos, pi, and sqrt. Filtering is a convention-based shortcut, not a complete definition of the public API.

Public API Conventions and __all__

A name beginning with one underscore, such as _parse_value, is conventionally treated as non-public. This is a signal to readers and tools, not a strict access restriction. Python still allows code in another module to access it.

A module can define __all__ as a list of names intended for wildcard imports:

__all__ = ["welcome", "bye"]

__all__ can communicate the module's public interface and controls which names are imported by from simple_module import *. It serves a different purpose from dir().

  • dir(simple_module) reports names discoverable on the module object, including many special attributes and possibly private names.
  • simple_module.__all__ declares names selected by the module author for wildcard-import behavior and public-interface communication.

These two name sets can differ. Prefer explicit imports and documentation when using a module as a dependency.

Important Limitations of dir()

dir() is exploratory rather than a perfect contract. Objects can customize attribute access or directory listings dynamically, and some attributes may be generated only when requested.

If you know an attribute name, try getattr() directly:

value = getattr(simple_module, "bye", None)
print(value)

For reliable use of a library, consult its documentation and public API guidance. Use help(), inspect, or object-specific APIs when a simple name list is not enough.

Troubleshooting Module Inspection

ModuleNotFoundError during import

If import simple_module raises ModuleNotFoundError, check that the file name is exactly simple_module.py, that it is in the current working directory or an import-search location, and that you are using the intended Python interpreter and environment.

An expected name is missing

If you edited a module after importing it in an interactive session, the existing module object may still contain the earlier contents. Restart the interpreter during beginner exercises, or deliberately reload a module during development. Also check spelling and confirm that a different module with the same name was not imported.

print(getattr(simple_module, "__file__", None))

This can help confirm which file-based module was loaded when __file__ is available.

__file__ or __cached__ is missing

These attributes are optional metadata. Built-in, frozen, dynamically created, and some specially loaded modules do not have a normal source-file path or bytecode-cache path. Write portable inspection code with a fallback:

location = getattr(module_object, "__file__", None)
cache_location = getattr(module_object, "__cached__", None)

dir() contains too many names

Filter out names beginning with an underscore to focus on likely public names, then use help() and module documentation to determine which members are supported for normal use.

dir() does not show every dynamic name

Some objects customize attribute behavior or directory listings. Use getattr() for a known name, consult the documentation, and use inspect or an object-specific API when deeper investigation is needed.

Exam- and Practice-Ready Summary

  • A module is an importable unit that exposes names such as functions, classes, variables, constants, and metadata.
  • Import the module before inspecting it: import simple_module.
  • dir(simple_module) returns a list of attribute-name strings.
  • Normal names may be user-defined functions, classes, or variables; dunder names usually provide metadata or runtime support.
  • Important module metadata includes __doc__, __file__, __name__, __package__, __spec__, __loader__, __cached__, and __builtins__.
  • dir(simple_module.bye) inspects the function object, not just the source module.
  • Call a function with simple_module.bye() and read a variable with simple_module.GREETING.
  • Use help() for documentation, __doc__ for direct docstring access, getattr() for dynamic lookup, and inspect for deeper analysis.
  • A leading underscore conventionally marks a name as non-public, while __all__ declares names for wildcard-import behavior. Neither is the same as the complete result of dir().

For a focused reference, continue with displaying and inspecting Python module contents.