May 9, 2018

How to Generate PDF Files in Python with Xhtml2pdf, WeasyPrint or Unoconv

Vladimir Sidorenko
Vladimir Sidorenko

Programmatic generation of PDF files is a frequent task when developing applications that can export reports, bills, or questionnaires. In this article, we will consider three common tools for creating PDFs, including their installation and converting principles.

PDF stands for Portable Document Format and it was originally developed by Adobe, though, it has now become an open standard for text files. Creating a single PDF file from a Microsoft Word document can be easily done through the Word’s menu, print dialogue in Linux or MacOS, or Adobe Acrobat Reader. At the same time, when you need to generate tens, hundreds, or even thousands of PDF files, it is better to automate this task. For generating PDFs with Python, we have chosen the following solutions: Xhtml2pdf, Weasyprint, and Unoconv.

How to Generate PDF in Python with Xhtml2pdf

The main drawback of all HTML to PDF converters is that the latter has numerous aspects that are absent in HTML, including, for example, page size. Xhtml2pdf deals with this problem by adding specific markup tags that allow solving various tasks, such as converting headers and footers on all pages. Xhtml2pdf is a CSS/HTML to PDF generator/converter and Python library that can be used in any Python framework such as Django.

In fact, to create PDFs, the tool uses ReportLab, a common open source Python library for generating PDF files. ReportLab uses an XML-based markup language called Requirements Modelling Language (RML). Therefore, you can think of Xhtml2pdf as another markup language for the ReportLab library.


You can easily install Xthml2pdf using a common command:

pip install xhtml2pdf

Generating PDFs

Xhtml2pdf usage example:

from xhtml2pdf import pisa
import cStringIO as StringIO
from django.template.loader import get_template
from django.template import Context
def html_to_pdf_directly(request):
	template = get_template("template_name.html")
	context = Context({'pagesize':'A4'})
	html = template.render(context)
	result = StringIO.StringIO()
	pdf = pisa.pisaDocument(StringIO.StringIO(html), dest=result)
	if not pdf.err:
		return HttpResponse(result.getvalue(), content_type='application/pdf')
	else: return HttpResponse('Errors')

You should create a view that would convert a PDF file from HTML. To temporarily store your PDF, use the cStringIO library that will provide an efficient file-like object interface. Set an output HTML file that has to be converted into PDF and the one which will receive the final result. Then you should set the HttpResponse object that has proper headers and enter the command that will get a value from the StringIO buffer and show it as a response.

How to Convert HTML to PDF in Python with WeasyPrint

WeasyPrint is another visual rendering engine that can export HTML/CSS content to PDF. Its main focus is to support web standards for further printing. WeasyPrint is a free tool that is available to download and use under a BSD license. The solution uses different libraries, but it is not based on a particular rendering engine, such as Gecko or Webkit. WeasyPrint’s CSS layout engine is based on Python and it supports 2.7 and 3.3 or higher Python versions. It is worth noting that this engine is created specifically for pagination tasks. In addition, WeasyPrint supports Django.


The tool supports common HTML and CSS files, data URIs, FTP, and HTTP. It means that WeasyPrint supports HTTP redirects, but it does not support more complex features, such as authentication or cookies. The solution also supports CSS stylesheets both linked by the element and embedded in the </i> element. When it comes to images, WeasyPrint supports various elements, such as <i><object></i>, <<i>img></i>, and <i><embed></i>, and image formats, including:</p><ul><li>JPEG,</li><li>GIF,</li><li>SVG,</li><li>and PNG.</li></ul><p>The tool does not, however, rasterize SVG images. Instead, it renders such images as vectors in the output PDF file.</p><p>Furthermore, WeasyPrint supports attachments, bookmarks, and hyperlinks. The tool renders clickable hyperlinks in the event that you are using a convenient PDF viewer. WeasyPrint supports both internal (<i><a href “#name”></i>) anchors and external hyperlinks. The tool usually displays bookmarks in a sidebar and embeds attachments in a converted PDF file.</p><h3>Installation</h3><p>Since WeasyPrint contains many dependencies, you can easily install it by running a <i>pip</i> command when using Python to create a PDF:</p><p><i><code>pip install Weasyprint</code></i></p><p>Then, you should make the tool executable by entering the following code that will show up in your WeasyPrint version:</p><p><i><code>weasyprint --version</code></i></p><h3>Generating PDF</h3><p>To convert HTML/CSS content into a PDF without any changes, you can simply enter the following code:</p><p><i><code>weasyprint ./path_for_storing_your_PDF/file_name.pdf</code></i></p><p>If you need to change the styles of your content in a future PDF file, you have to set your stylesheets:</p><p><i>from weasyprint import HTML, CSS</i></p><p><i>HTML(‘’).write_pdf(‘/path_for_storing_your_PDF/file_name.pdf’,</i></p><p><i>stylesheets=[CSS(string=’body { font-color: red }’)])</i></p><p>The below-mentioned WeasyPrint usage examples will allow you to convert PDFs, even when some changes are required.</p><p>To add a CSS file, run the following code:</p>

from django.conf import settings

CSS(settings.STATIC_ROOT + ‘css/main.css’)

Ex: HTML(‘’).write_pdf(‘/yourdirectory/file.pdf’,
	stylesheets=[CSS(settings.STATIC_ROOT + ‘css/main.css’)])

To convert an existing HTML template into a PDF file, use the following Django functions:

from weasyprint import HTML, CSS
from django.template.loader import get_template
from django.http import HttpResponse

def pdf_generation(request):
	Html_template = get_template(‘template/home_page.html’)
	pdf_file - HTML(string-html_template).write_pdf()
	response = HttpResponse(pdf_file, content_type=’application/pdf’)
	response[‘Content-Disposition’] = ‘filename=”home_page.pdf’’’
	return response

How to use Python to Generate PDFs with Unoconv

Unoconv stands for Universal Office converter. It is a command line solution for converting Libre/OpenOffice files into various formats, including PDF. To convert a file, the tool first reads a necessary file using a listener. If it does not find any available listener, Unoconv can start its own office instance.


Unoconv can convert any file format supported by OpenOffice, and it includes more than 100 file formats.

Supported file formats for exporting to include:

  • doc
  • odt
  • html
  • pdf
  • txt
  • xhtml
  • rtf
  • ooxml, etc.

You also can use this tool for batch processing and apply your own style templates to an existing file you need to convert. If needed, Unoconv can autostart OpenOffice for your processing activities. The solution supports OpenOffice on common desktop operating systems, such as Windows, Linux, and MacOSX. To process your documents centrally, you can use Unoconv in both your client and server environments.


To install Unoconv on Linux, use the sudo apt-get install command and enter it into your command line:

$ sudo apt-get install -Vy libreoffice unoconv

Python: PDF Creation using Unoconv

$ pip install python-docx
from docx import Document
import subprocess

# edit the Microsoft Word file
document = Document(‘yourfile.docx’)
for paragraph in document.paragraphs:

 	subprocess.check_call([‘/usr/bin/python3’, ‘/usr/bin/unoconv’, ‘-f’, ‘pdf, ‘-0’, ‘yourdocument_new’])
except subprocess.CalledProcessorError as e:
	print(‘CalledProcessorError’, e)

Unoconv allows users to edit Microsoft Office files before converting. For that purpose, you should set the document you need to edit, enter necessary procedures, and set the command that will initiate saving your document. To convert a Microsoft Word document into PDF in Python, enter the above-mentioned code.

The important differences between these three tools are in their number of supported formats of files and graphics, as well as the preciseness of converting complex content that contains some advanced elements, such as hyperlinks, custom styles, cookies, etc. In fact, a list of available tools that ensures Python PDF generation from other file formats is a bit longer, but we have covered the solutions we have used for our own tasks. One way or another, each of these tools will significantly facilitate your work when you need to create lots of PDF files.

More thoughts

Mar 7, 2017Technology
How Do You Use MongoDB With Python?

There are many ways to interact with MongoDB using Python. In this article we'll compare them and will help you make a decision.

Vlada Oliinyk
Vlada Oliinyk
Jun 14, 2017Technology
How to Deploy a Django Application on Heroku?

In this article I'll show you how to deploy Django with Celery and Postgres to Heroku.

Vladimir Kalyuzhny
Vladimir Kalyuzhny
Mar 6, 2010Technology
Ajax form validation

There was a task to submit form with ajax, with server side validation of course. Obvious solution is to do validation and return json with erros. I didn't like idea of writing separate view for validation and then inserting errors in form html on client side. Especially since I already had a generic template for django form with errors display. In this article I'll describe how I solved the task.

Vladimir Sidorenko
Vladimir Sidorenko
Feb 12, 2020Technology
5 Best Payment Gateways For 2020

We reviewed the best payment gateways in 2020. Here’s our comparison of their features, advantages, and disadvantages.

Vladimir Sidorenko
Vladimir Sidorenko
Feb 28, 2010Technology
Composing multiple views in Django

In UNIX way, each view should solve single task. This is good idea, but sometimes we need to mix logic of different views on same page. Filter, sort, paginate, or, for example, add comment on product page. In this article I'll show how we can mix such multiple views.

Vladimir Sidorenko
Vladimir Sidorenko
Jan 12, 2017Technology
Making Custom Report Tables Using AngularJS and Django

In this article I will tell you how to create an interactive interface with a widely customized visual look and different filtering to view reports.

Pasha Volkov
Pasha Volkov