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
-
-
- 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
- Official pyfpdf Tutorial
- pyfpdf reference manual
thank you very muyh for this nice tutorial!
Pingback: Visto nel Web – 35 « Ok, panico
Pingback: 七周七è¯è¨€ä¹‹Python 课åŽä½œä¸š | TopGeek
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.
Thanks. I saw that post. I hoped you found a way to use Pyfpdf with Python 3. Any workaround (not using Python 2.X)?
Not that I’m aware of. I would ask the developers of the library when you can expect Py3 support. Mariano and Massimo are pretty receptive guys.
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
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!
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
Pingback: Other resources with pyFPDF examples | pyFPDF Book Tutorials
I believe the import would be like this now,
from fpdf import FPDF, HTMLMixin