Use Markdown README's in Python modules
If, like me, you regularly use Markdown to give your GitHub projects nice pretty README's, but are trying to submit your new swanky Python module to the Python Package Index, you may have hit a bit of a snag. To get your nicely formatted README on your module's PyPi page, you need to use reStructuredTxt. Now you could admit defeat and change your README, or you could do this:
Install Pandoc
Install pyandoc python module
pip install pyandoc
Create a file called register.py and add the following code:
import pandoc
import os
pandoc.core.PANDOC_PATH = '/path/to/pandoc'
doc = pandoc.Document()
doc.markdown = open('README.md').read()
f = open('README.txt','w+')
f.write(doc.rst)
f.close()
os.system("setup.py register")
os.remove('README.txt')
Now add the following code to the top of your setup.py file:
import os
long_description = 'Add a fallback short description here'
if os.path.exists('README.txt'):
long_description = open('README.txt').read()
and set the longdescription arg equal to `longdescription`
Now just register your module using
python register.py
and your Pypi page should have it's own nicely formatted instructions.
Basically all your doing is creating a temporary reStructeredTxt file for setup.py to read in, but avoiding trying to do any pandoc conversion in setup.py like I originally had, which caused issues for installing on other systems.
Written by Will McKenzie
Related protips
12 Responses
Here's what I ended up doing:
# I really prefer Markdown to reStructuredText. PyPi does not. This allows me
# to have things how I'd like, but not throw complaints when people are trying
# to install the package and they don't have pypandoc or the README in the
# right place.
try:
import pypandoc
description = pypandoc.convert('README.md', 'rst')
except (IOError, ImportError):
description = ''
and then using description in setup() as you'd expect.
Typo: Seems like "pyandoc" should actually say "pypandoc".
Unfortunately, on Python 2.7 the command "pypandoc.convert()" can't cope with non-ASCII characters. Is this an issue of restructured text, pypandoc or pandoc?
Hi, that isn't actually a typo. There is also a module called pyandoc. I'm unaware as to whether that has the same issue with non-ASCII characters though.
Thanks for making this!
@xiongchiamiov: I too preferred to use pypandoc
instead of pyandoc
. However, I modified your code so that if pypandoc
had problems, the description would just be the README.md
as markdown.
try:
import pypandoc
description = pypandoc.convert('README.md', 'rst')
except (IOError, ImportError):
description = open('README.md').read()
Following some of the suggestions above, but using the software described in this article, here's a gist of my solution.
https://gist.github.com/aubricus/9184003#file-setup_snippet-py
I went this way mostly because I was also encountering the non-ASCII character issues while using pypandoc (in lieu of pyandoc, which was suggested by some of the commenters).
Also for those interested in sort of managing Pandoc through Homebrew: Install Pandoc With Homebrew
Clever workaround, but the best solution would be to petition PyPI to support Markdown (as well as Restructured Text). It's a pervasive format, used on Github and StackOverflow. It shouldn't be necessary to learn a new markup language or rewrite your documentation to publish a Python package.
Npm (the Nodejs) package manager and its registry support Markdown readmes. See, for example, https://www.npmjs.org/package/yargs
If you would like PyPI to support Markdown readmes, please comment on the feature request at https://bitbucket.org/pypa/pypi/issue/148/support-markdown-for-readmes
Done! Would definitely be better if they supported Markdown without all the faff!
For those of you using pypandoc to convert, you may encounter an issue, like me, where only the first line of the original readme appears on pypi. You need to add one line to fix that :
try:
long_description = pypandoc.convert('README.md', 'rst')
long_description = long_description.replace("\r","") # YOU NEED THIS LINE
except OSError:
print("Pandoc not found. Long_description conversion failure.")
import io
# pandoc is not installed, fallback to using raw contents
with io.open('README.md', encoding="utf-8") as f:
long_description = f.read()
(This piece of code comes from pypandoc repo itself in case you're not convinced)
Useful, but I prefer rst > <