An Intro to pyfpdf – A Simple Python PDF Generation Library

Today we’ll be looking at a simple PDF generation library called pyfpdf, a port of FPDF which is a php library. This is not a replacement for Reportlab, but it does give you more than enough to create simple PDFs and may meet your needs. Let’s take a look and see what it can do!

Note: PyFPDF is no longer maintained. It has been replaced with fpdf2

Installing pyfpdf

You can just use pip to install pyfpdf:

pip install pyfpdf

Taking pyfpdf for a Test Drive

As with any new library, you need to actually write some code to see how it works. Here’s one of the simplest scripts you can make that will create a PDF:

import pyfpdf

pdf = pyfpdf.FPDF(format='letter')
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.cell(200, 10, txt="Welcome to Python!", align="C")
pdf.output("tutorial.pdf")

Note that when we initialize our FPDF object we need to tell it that we want the result to be “letter” size. It defaults to “A4”. Next we need to add a page, set the font and put some text in. The pdf.cell call was a little unintuitive. The first two arguments are width and height and kind of specify the location of the text you pass in. The align parameter only takes single letter abbreviations and you’ll have to look in the source to figure those out. In this case, we’re centering the text by passing it a “C”. The last line accepts two parameters: the pdf name and the destination. If there’s no destination present, then the PDF is output to the same directory that the script is run in.

What if you wanted to add another line? Well you can add more text to the end if you edit how big the cell is and just create another cell. If you need a line break, then you can change the code to the following:

import pyfpdf

pdf = pyfpdf.FPDF(format='letter')
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.cell(200, 10, txt="Welcome to Python!", ln=1, align="C")
pdf.cell(200,10,'Powered by FPDF',0,1,'C')
pdf.output("tutorial.pdf")

Which results in the following PDF: tutorial.pdf

Adding Bling with Headers, Footers and PageBreaks

The tutorial that is included on pyfpdf’s Google Code site shows how to do headers, footers and page breaks. It doesn’t run due to a method name that must have changed and the code is written using “this” instead of “self”, so I rewrote it and cleaned it up a bit. Here’s the code:

import pyfpdf

########################################################################
class MyPDF(pyfpdf.FPDF):
    """"""

    #----------------------------------------------------------------------
    def header(self):
        """
        Header on each page
        """
        # insert my logo
        self.image("logo.png", x=10, y=8, w=23)
        # position logo on the right
        self.cell(w=80)
        
        # set the font for the header, B=Bold
        self.set_font("Arial", style="B", size=15)
        # page title
        self.cell(40,10, "Python Rules!", border=1, ln=0, align="C")
        # insert a line break of 20 pixels
        self.ln(20)
    
    #----------------------------------------------------------------------
    def footer(self):
        """
        Footer on each page
        """
        # position footer at 15mm from the bottom
        self.set_y(-15)
    
        # set the font, I=italic
        self.set_font("Arial", style="I", size=8)
        
        # display the page number and center it
        pageNum = "Page %s/{nb}" % self.page_no()
        self.cell(0, 10, pageNum, align="C")
        
#----------------------------------------------------------------------
if __name__ == "__main__":
    pdf = MyPDF()
    pdf.alias_nb_pages()
    pdf.add_page()
    pdf.set_font("Times", size=12)
    
    # put some lines on the page
    for i in range(1, 50):
        pdf.cell(0, 10, "Line number %s" % i, border=0, ln=1)
    pdf.output("tutorial2.pdf")

Which creates the following PDF: tutorial2.pdf

This time around, we create a subclass of FPDF and override its header and footer methods as they don’t actually do anything anyway (i.e. they’re stubs). In our header, we create an image object and pass in a logo file as well as the x/y location and the width (23) of the logo. You can also pass a height too if you care about keeping the aspect ratio sane. Then we position it and insert a string of text for the title. Finally, we put in a line break.

The footer is set up to be 15 mm from the bottom. It’s also in 8pt Arial Italic. The error in the official tutorial is that it calls self.PageNo(), but that doesn’t exist. However there is a page_no method that seems to replace it, so I used that. Then at the bottom of the script, we actually create our pdf object and tell it to write a bunch of lines. If you run this script, you should get a 3-page document.

Using pyfpdf to Generate a PDF from HTML

One of my readers pointed out that pyfpdf can also generate a PDF from basic HTML. I don’t know how I missed that, but it’s true! You can! You can read about it on the project’s wiki. I am reproducing a slightly modified example below:

html = """

html2fpdf

 

Basic usage

 

You can now easily print text while mixing different styles : bold, italic, underlined, or all at once!
You can also insert hyperlinks like this www.mousevspython.comg, or include a hyperlink in an image. Just click on the one below.

Sample List

 

    • option 1

 

      1. option 2

 

  • option 3

 

Header 1header 2

 

cell 1cell 2

 

cell 2cell 3

“”” from pyfpdf import FPDF, HTMLMixin class MyFPDF(FPDF, HTMLMixin): pass pdf=MyFPDF() #First page pdf.add_page() pdf.write_html(html) pdf.output(‘html.pdf’,’F’)

Which will create the following PDF: html.pdf

Wrapping Up

There’s one more tutorial on their website that talks about colors and line breaks, but I’ll leave that for you to do as an exercise. I didn’t see anything in here about drawing, inserting tables or graphs, custom font embedding or the many other features that are available in Reportlab, but then again this is supposed to be a simple PDF generation library. If you need more advanced features, then you should certainly look at Reportlab or even some of the offshoot projects that are based on it (rst2pdf or xhtml2pdf come to mind).

Further Reading

Source Code

11 thoughts on “An Intro to pyfpdf – A Simple Python PDF Generation Library”

  1. Pingback: Visto nel Web – 35 « Ok, panico

  2. Pingback: 七周七语言之Python 课后作业 | TopGeek

  3. Thanks for this. It was really helpful. It looks like you can now install via pip or easy_install.
    “pip install fpdf” did the trick for me.

  4. Thanks. I saw that post. I hoped you found a way to use Pyfpdf with Python 3. Any workaround (not using Python 2.X)?

  5. Great tutorial! Question: I will have a need soon to dynamically generate hundreds of certificates in PDF format. The data that needs to go onto each PDF (name, class name, date, etc.) will be imported from a csv file. *Ideally* I was hoping that I could use an existing image as a background for the PDF page. The image would just be the certificate (corporate logo, graphics, lines for text), and then just add text cells/fields over top of it so that when each PDF is generated, it is all one single page. Hope that makes sense. I’ll look to try it soon but was hoping you could verify whether that is possible with this library, and if not, recommend another? I’m relatively new to Python.

    Mark

  6. Thanks Mike. I will give it a shot and try ReportLab if I must. ReportLab looks like it will take more up-front study from me to get it to do what I need it to do. But at least I know there is a solution. Thanks again!

  7. I’m using pyfpdf 1.54 to output html tables into a pdf file. Everything is 100% fine except I can’t figure out how to adjust row height or font size inside the table cells.

    Font size is the big issue, if I can make the default font smaller my layout can fit Portrait – instead of Landscape. I have a 10 column layout.

    Thanks for the tutorial.

    Len

  8. Pingback: Other resources with pyFPDF examples | pyFPDF Book Tutorials

Comments are closed.