I am trying to use pydoc to generate documentation for my code. Basically everything goes smoothly - I input my docstrings and run python -m pydoc on the module and an html file is written.
But the output html file is "plain vanilla" with no nice formatting: white background, no colors to highlite, ugly serif font etc.:
What I am looking for is output formatted like this:
I couldn't find help on how to format the output.
EDIT: After a while, I believe some other tool than PyDoc might offer more flexibility in terms of formatting the output. No really helpful and simple answers to my original question have come.
2 Answers 2
I have exactly the same problem. It was particularly frustrating because apparently everybody else is getting the nicely formatted html page according to some YouTube video.
Then I did a little digging in pydoc.py. I realize pydoc is indeed writing a html page without any style sheets when you call pydoc.writedoc(), which is what you get when you type
pydoc -w myModule
in the terminal. However, when you use
pydoc -b myModule or pydoc -p myModule
the style sheet seems to be available. This means the your local server generates the html using a different function. Then I tracked down the html.page() function and realize there're 2 versions:
The original HTMLDoc(Doc) version and the overridden version in a locally defined class _HTMLDoc(HTMLDoc) inside _url_handler(). The overridden version is really what we want. So here's my hack:
- Find your pydoc.py, mine (Windows 11) is in C:/Users/MyUserName/AppData/Local/Programs/Python/Python312/Lib/pydoc.py
- Find class HTMLDoc(Doc) and class _HTMLDoc(HTMLDoc). They both have a function page()
- Replace page() in class HTMLDoc(Doc) with the one in class _HTMLDoc(HTMLDoc). Now because the one in class _HTMLDoc(HTMLDoc) also calls another function html_navbar(), you'll have to copy html_navbar() over as well. In particular this means replacing original HTMLDoc.page() code: HTMLDoc.page() without using _pydoc.css
with:
def page(self, title, contents):
"""Format an HTML page."""
css_path = "file://C|/Users/MyUserName/AppData/Local/Programs/Python/Python312/Lib/pydoc_data/_pydoc.css"
css_link = (
'<link rel="stylesheet" type="text/css" href="%s">' %
css_path)
return """\
<!DOCTYPE>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Pydoc: %s</title>
%s</head><body>%s<div style="clear:both;padding-top:.5em;">%s</div>
</body></html>""" % (title, css_link, self.html_navbar(), contents)
def html_navbar(self):
version = html.escape("%s [%s, %s]" % (platform.python_version(),
platform.python_build()[0],
platform.python_compiler()))
return """
<div style='float:left'>
Python %s<br>%s
</div>
<div style='float:right'>
<div style='text-align:center'>
<a href="index.html">Module Index</a>
: <a href="topics.html">Topics</a>
: <a href="keywords.html">Keywords</a>
</div>
<div>
<form action="get" style='display:inline;'>
<input type=text name=key size=15>
<input type=submit value="Get">
</form>
<form action="search" style='display:inline;'>
<input type=text name=key size=15>
<input type=submit value="Search">
</form>
</div>
</div>
""" % (version, html.escape(platform.platform(terse=True)))
- Be aware I also changed the css_path variable in the new page() function to be an absolute path to my file.
This worked for me perfectly! Now I have to figure out why it originally works for some people and not me... Hope this helps.
1 Comment
There is an issue on that https://github.com/python/cpython/issues/127276
The solution proposed there can also be adapted in your own code:
import pydoc
import importlib.resources
css_data = importlib.resources.files('pydoc_data').joinpath('_pydoc.css').read_text()
pydoc.writedoc(module) # this is the equivalent to pydoc -w
with open(module.__name__ + ".html") as inp:
html = inp.read()
with open(module.__name__ + ".html", "w") as out:
out.write(html.replace("</head>", "<style>%s</style></head>" % css_data))