Well-written docstrings can become interactive help, terminal pages, and HTML documentation without an external documentation package. Python pydoc inspects modules, classes, functions, and methods and generates documentation from __doc__, signatures, inheritance, and documentable members.
Pydoc is useful for exploring libraries, reviewing internal APIs, generating quick reference pages, and understanding objects during development. It does not replace every feature of Sphinx or MkDocs, and it requires caution because it imports documented modules, executing their top-level code. This guide covers commands, docstrings, HTML generation, search, the local server, help(), environment selection, and safe imports.
It complements our guides to Python inspect, types, sysconfig, platform, and py_compile.
How pydoc finds documentation
For modules, classes, functions, and methods, pydoc reads the object’s docstring and recursively examines documentable members. When no docstring exists, it can try to obtain a block of comments immediately above the definition through inspect.getcomments().
Docstrings are the predictable source. Normal comments should explain implementation details; docstrings should describe the public contract.
A simple docstring
def calculate_total(values, rate=0):
"""Return the sum of values plus a percentage rate.
Args:
values: A sequence of numbers.
rate: Additional percentage.
Returns:
The calculated total.
"""
subtotal = sum(values)
return subtotal * (1 + rate / 100)Pydoc displays the text and callable signature. It does not verify that documentation matches behavior, so tests and code review remain necessary.
Using help inside Python
help(calculate_total)
help("json")
help(str.split)The built-in help() function uses pydoc’s online help system to render text in the console. It accepts objects and searchable names.
Running pydoc in a terminal
python -m pydoc json
python -m pydoc pathlib.Path
python -m pydoc my_package.module.functionThe argument can be a module, package, class, method, function, or dotted reference. The output resembles a Unix manual page.
Documenting a source-file path
When an argument contains the operating system’s path separator and points to an existing Python source file, pydoc can document that file.
python -m pydoc ./tools/report.pyUse controlled paths. A web service should not allow users to select arbitrary server files for documentation.
Important: pydoc imports modules
To find objects, pydoc imports the target module. Every top-level statement can run.
# Dangerous import-time effects
connection = open_production_database()
start_worker_thread()Generating documentation could therefore open connections, start threads, modify files, or send network requests.
Protect execution with __main__
def main():
run_application()
if __name__ == "__main__":
main()Place command execution behind the guard. Imports should define objects and perform only minimal, predictable initialization.
Imports can fail
Missing optional dependencies, required environment variables, incompatible native libraries, and network access at import time can prevent documentation generation.
Design modules so their imports are safe and failure messages identify optional dependencies without exposing secrets.
Terminal pagination
For long output, pydoc attempts to use a pager. The MANPAGER and PAGER environment variables can select the program, with MANPAGER taking priority.
CI and redirected output may behave differently. Automation should not depend on interactive pagination.
Writing HTML
python -m pydoc -w my_packageThe -w flag writes HTML into the current working directory. Confirm the destination and permissions before running it.
Generate into a clean build directory to avoid mixing stale pages with new documentation.
Writing several pages
python -m pydoc -w package.module_a package.module_bFor a large documentation website, a dedicated generator provides better navigation, theming, cross-references, search, and publishing workflows.
Searching module synopses
python -m pydoc -k databaseThe -k option searches synopsis lines of available modules. A module’s synopsis is normally the first line of its docstring.
Write a short, informative first line so search results remain useful.
A good module docstring
"""Generate financial reports in CSV and PDF.
The module contains validators, formatters, and exporters.
"""Separate the synopsis from the longer explanation with a blank line.
Starting the local HTTP server
python -m pydoc -p 1234The command starts a server on localhost. Port zero chooses an unused port.
python -m pydoc -p 0The interface provides module, topic, keyword, and search pages.
Opening a browser automatically
python -m pydoc -bThe option starts the server and opens the module index in the default browser.
Choosing a hostname
python -m pydoc -n 0.0.0.0 -p 8000A non-local host can make the service reachable from another machine, which may help when developing inside a container. It also increases exposure.
The server is not for production
The official documentation explicitly limits the HTTP server to local development. It does not provide production-grade authentication, authorization, TLS, request limits, hardening, or observability.
Do not expose internal modules or application details on a public interface.
The current environment selects the module
Pydoc uses the active sys.path and environment. It documents the same module version that would be imported by that interpreter.
python -c "import sys; print(sys.executable)"
python -m pydoc my_packageActivate the intended virtual environment and verify the executable first.
Multiple Python installations
Invoking a standalone pydoc command can select a different installation. Prefer python -m pydoc with the exact interpreter required.
PYTHONDOCS
For standard-library modules, pydoc assumes official documentation lives under docs.python.org/X.Y/library/. The PYTHONDOCS variable can point to another URL or a local Library Reference directory.
Control this variable in reproducible environments to avoid incorrect links.
Function signatures
Pydoc uses inspect.signature() to display callable signatures. Decorators that fail to preserve metadata can hide the original interface.
from functools import wraps
def record(function):
@wraps(function)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapperwraps() preserves the name, docstring, annotations, and wrapped-function metadata.
Classes and inheritance
Class documentation can show methods, attributes, bases, and inherited behavior. A class docstring should explain responsibility, invariants, construction, and important lifecycle rules.
class Customer:
"""Represent a validated application customer."""Properties and descriptors
Properties and descriptors can appear in generated output. Introspection should not trigger destructive work. Keep class-level access and descriptor metadata safe.
Type hints
Annotations improve generated signatures, but pydoc is not a static type checker. Document units, ranges, exceptions, mutation, and side effects that the type cannot express.
Documenting exceptions
def divide(a, b):
"""Divide a by b.
Raises:
ZeroDivisionError: If b is zero.
"""
return a / bFocus on errors callers can reasonably handle.
Public and private APIs
Names beginning with an underscore communicate internal use, but introspection can still find them. Define __all__, organize public imports, and avoid exposing accidental implementation objects.
Never place secrets in docstrings
Do not include real tokens, private URLs, customer data, or infrastructure credentials in examples. Documentation can be generated and distributed automatically.
Executable examples
Pydoc displays examples but does not execute them. doctest can run compatible examples separately. Keep examples deterministic, safe, and free of production side effects.
Testing documentation generation
A CI step can import modules and generate HTML to detect broken imports and malformed metadata.
python -m pydoc -w my_package.moduleRun the job in isolation, without production credentials, and block network access when appropriate.
pydoc versus Sphinx
Pydoc is excellent for exploration and quick reference documentation. Sphinx provides narrative pages, cross-references, extensions, themes, and structured publishing.
The tools can coexist: strong docstrings benefit pydoc, IDEs, help systems, and larger generators.
pydoc versus help
help() is the interactive interface inside Python. python -m pydoc adds terminal commands, search, HTML output, and the local server.
Common mistakes
- Running production side effects during import.
- Generating docs with the wrong Python installation.
- Exposing the HTTP server publicly.
- Writing module docstrings without a clear synopsis.
- Losing signatures in decorators.
- Including secrets in examples.
- Assuming pydoc validates correctness.
- Writing HTML into the wrong directory.
Best practices
- Keep imports safe and lightweight.
- Use the
__main__guard. - Run through
python -m pydoc. - Activate and verify the intended environment.
- Write contract-focused docstrings.
- Preserve signatures with
wraps(). - Restrict the server to development.
- Test generation in isolated CI.
Conclusion
Python pydoc turns docstrings and introspection into terminal help, HTML, keyword search, and local browsing. It is a practical tool for exploring APIs and generating reference documentation quickly.
Because it imports code, modules must be safe to import and the HTTP server must remain a development utility. Consult the official pydoc documentation and PEP 257 for clearer docstring conventions.







