Python-Markdown
| Language | Python (3.11+ for the current version) |
|---|---|
| License | BSD-3-Clause |
| Repository | github.com/Python-Markdown/markdown |
| Documentation | python-markdown.github.io |
| Depends on | nothing |
| Read / write | parses Markdown (original syntax rules) plus extensions; renders HTML |
Python-Markdown implements John Gruber’s original Markdown description, not CommonMark. The differences show up in edge cases: nested list items need 4 spaces of indentation, and emphasis and HTML blocks follow the older rules. On top of that it has a large set of official extensions (tables, fenced_code, footnotes, toc, attr_list, def_list, abbr, admonition, codehilite, meta, md_in_html, sane_lists, smarty, wikilinks) and an API for writing your own. Third-party collections like PyMdown Extensions add task lists, strikethrough, math and more. MkDocs and many static site tools use it.
It passes raw HTML through and has no safe mode (removed in 3.0). Sanitize output (for example with nh3) when the input isn’t trusted.
Installation#
pip install markdown
Basic usage: convert Markdown to HTML#
import markdown
with open("README.md", encoding="utf-8") as f:
text = f.read()
html = markdown.markdown(text, extensions=["tables", "fenced_code", "footnotes"])
with open("README.html", "w", encoding="utf-8") as f:
f.write(html)
How to generate a table of contents#
import markdown
md = markdown.Markdown(extensions=["toc"])
html = md.convert(text) # headings get id attributes
print(md.toc) # <div class="toc"><ul>...</ul></div>
for item in md.toc_tokens: # nested dicts: level, id, name, children
print(item["level"], item["name"], item["id"])
How to read metadata at the top of a file#
The meta extension reads Key: value lines (MultiMarkdown style) before the first blank line:
md = markdown.Markdown(extensions=["meta"])
html = md.convert("Title: Release notes\nAuthor: Ann\n\n# Notes\n")
print(md.Meta) # {'title': ['Release notes'], 'author': ['Ann']}
For YAML front matter between --- lines, strip it first with a package like python-frontmatter.
How to convert a file directly#
markdown.markdownFromFile(input="README.md", output="README.html", encoding="utf-8",
extensions=["tables"])
From the command line: python -m markdown -x tables README.md > README.html.
How to get closer to CommonMark list behavior#
html = markdown.markdown(text, extensions=["sane_lists"])
sane_lists stops ordered and unordered lists from mixing and respects the first number of an ordered list. For full CommonMark behavior use markdown-it-py.
Tips#
- Reuse a
Markdowninstance for many documents, callingmd.reset()between them to clear state like the TOC and footnotes. - Extension options are passed with
extension_configs={"toc": {"permalink": True}}. - Output is HTML fragments without
<html>or<body>.