Jonas Neubert

… works with bits and atoms

The Best Python Packages for Generating Barcodes

Published - Jan 23 2019

(Updated: )

Barcodes are a cheap and ubiquitous way to add machine-readable information to an object. I think of barcodes as the real-world equivalent of browser cookies: For example, when you arrive at airport departures, the airline hands you a boarding pass with a barcode (the cookie). From that point onward you’re asked to show your barcode at every interaction: at security, the duty-free shop, and the boarding gate. And just like the information stored in browser cookies, the information in barcodes isn’t in plain sight but easily made visible.

While preparing a conference talk about barcodes, I spent three evenings researching Python packages for generating images of 1D and 2D barcodes. This review article is the result of that work.

This article was last updated on January 23th, 2019.

Summary: Recommendations

treepoem is the most feature-rich Python package for rendering barcodes as images. It supports all common barcode symbologies as well as many obscure ones, is actively maintained, and is available under the MIT license. It’s my recommendation for anyone who wants to work with many symbologies.

However, treepoem requires non-Python dependencies which might be difficult or impossible to install in some situations. If you cannot install treepoem’s dependencies, or just don’t want to, the next best general purpose option is python-barcode, the most actively maintained fork of the dormant pyBarcode package.

To generate barcodes of only a single symbology, I recommend these libraries: segno for QR and MicroQR, pdf417gen for PDF417, pylibdmtx for Datamatrix, and PubCode for Code 128.

Overview Table

Packagelast updatedLicenseOctocat (Github logo)Python versionsUPC-AEAN-13ISBNPZNI. 2 of 5Code 39Code 93Code 128DatamatrixPDF417QRMicro QRAztecOutput
treepoemAug 2018MIT282, 3req. Pillow
pyBarcodeJul 2013MITN/A2, (3)SVG, opt. Pillow
python-barcode
(fork of pyBarcode)
Jun 2018MIT47>= 3.5SVG, opt. Pillow
viivakoodi
(fork of pyBarcode)
Nov 2014MIT292, 3SVG, opt. Pillow
steenzout.barcode
(fork of viivakoodi)
Jan 2017MIT52, 3SVG, opt. Pillow
reBarcode
(fork of viivakoodi)
Oct 2017MIT02, 3SVG, opt. Pillow
pyStrich
(fork of huBarcode)
Jul 2016ApacheN/A3req. Pillow
code128Jan 2015LGPLN/A3SVG, opt. Pillow
PubCodeAug 2015MIT12, (3)req. Pillow
candybarAug 2016Apache22, 3req. Pillow
pydmtx (libdmtx)Feb 2015LGPL-2.1N/A2req. Pillow
pylibdmtxJan 2017MIT212, 3req. Pillow
pdf417genNov 2018MIT222, 3req. Pillow
pdf417
fork of pdf417gen
Nov 2018MIT02, 3req. Pillow
qrcodeJan 2019BSD1,6392, 3SVG, pypng, opt. Pillow
PyQRCodeJun 2016BSD218SVG, pypng
segnoOct 2018BSD272, 3see notes
qrcodegenNov 2018MITN/A2, 3see notes

treepoem in detail

treepoem stands out by the sheer number of supported symbologies and symbology variants. The way this feat is achieved, however, brings with it a few possible downsides.

The Python package treepoem is a wrapper around the Postscript program BWIPP. treepoem invokes Postscript using subprocess.Popen() meaning that Postscript must already be installed and subprocess available. This may be a problem if you are trying to generate barcode images in a shared environment such as a notebook server, to name just one example. In addition, treepoem requires the Pillow package for producing image file formats (see the section “Image file format exporters” below for why this matters).

If you are not affected by any of these potential stumbling blocks, then treepoem is refreshingly easy to use.

To install:

pip install treepoem

To use as a command line tool:

treepoem --type code128 --output code128.png PyBay2018

Some barcode types have options for the generator. This example sets the eclevel flag to control the error correction level of the QR Code. To know which options are available for a barcode type, use the BWIPP docs as reference:

treepoem --type qrcode --output qr.gif \
    https://jonasneubert.com/talks/pybay2018.html \
    eclevel=Q

To use as a library, this is the same example as Python code:

import treepoem

img = treepoem.generate_barcode(
    barcode_type='qrcode',
    data='https://jonasneubert.com/talks/pybay2018.html',
    options={"eclevel": "Q"}
)
img.convert('1').save('qr.gif')

A selection of barcodes generated with treepoem, using symbologies from the common to the obscure. Columnwise starting in top left: UPC-A, Maxicode, Code 128, Royal Mail 4 State Customer Code, QR Code, Italian Pharmacode, Aztec Code.

By the way, the name: barcode → bark ode → tree poem (source).

Criteria

Compared to web frameworks, data science tools, and the many other problem spaces addressed by open source Python packages, barcodes are only a small niche. However, barcode standards change at a glacial pace, resulting in an ecosystem where even packages that have not been maintained for a decade may enjoy active use. This section contains a few notes explaining the thought process by which I winnowed the list of several dozen options down to those listed in the comparison table and ultimately decided on my recommendations.

Must Haves

To be included in the review, a package must meet these criteria:

  • It is available on PyPI.
  • pip install [packagename] succeeds without errors on my 5-year-old MacBook.

Of course, an implicit requirement is that I must be able to discover the package. My methods of searching were:

  • Enter various barcode related terminology into the search box on pypi.org.
  • Search Stackoverflow for barcode related terminology.
  • Look at the list of forks for repos associated with packages I had already found.
  • Browse through the issue tracker of packages I had already found and follow links.

Supported Symbologies

Most users will be looking to generate barcodes of a single symbology only, and the summary at the top includes recommendations for single-symbology packages. If you require a symbology for which no such dedicated package exists or if you need to support many symbologies, you will be looking for a general purpose package that supports many symbologies.

The comparison table includes both types of packages. In deciding which packages to recommend, I generally favored those supporting more symbologies or, for “single symbology” packages, those supporting more variants of a symbology.

The comparison table includes columns for 13 symbologies. This might seem unfair because those 13 are an arbitrarily chosen subset of the fifty or so barcode symbologies that have some common use case today. My time and the available space on the conference slide deck were the reasons for this limitation. (A snide aside: If all Readme files were up-to-date with the package functionality, adding columns for additional symbologies would have been a lot easier!) Hopefully, my choice presents a useful balance by including the union set of common and frequently supported symbologies.

A further complication was that some symbologies are subsets of other symbologies and, in some cases, I disagree with the way symbology support is described in the package documentation or readme file. For example, many packages advertise support for ISSN. I do not include ISSN because it is simply an EAN-13 barcode with the first three digits equal to “977”. Similarly, the JAN (Japanese Article Number) symbology is sometimes listed separately but is actually identical to EAN.

Note that I omit the short versions of UPC and EAN, for example UPC-E and EAN-5, purely for space reasons. Most packages that support the long version also support the common short versions.

Project Activity and Popularity

Most barcode symbologies have been set in stone for decades. In theory, software for generating them could be truly complete, with zero remaining feature requests or bug fixes. However, even if bug-free software existed, some maintenance would be necessary because the Python language has evolved over the years, and so has the ecosystem of available tools for writing image file formats which many barcode generating tools utilize.

The usual tradeoff between project completeness and project activity applies: The more comprehensive the functionality and the higher the quality, the lower the project activity needs to be for a package to likely be a good choice for many users. I tried to find a reasonable balance, but my judgment is subjective. Sadly, the majority of packages I reviewed meet neither the threshold for completeness nor the threshold for activity.

To judge the level of project activity I relied mainly on the date of the most recent project release. In addition, I looked at the number of Github stars, where available, as an indicator of how much secondary activity to expect. Only qrcode benefited from this factor, but not enough to compensate for its lack of support for the Micro QR symbology in the head-to-head comparison with segno.

Python 3 support

It’s 2019, we are less than one year away from Python 2 officially becoming obsolete, a big part of the Python ecosystem has already abandoned it.

All recommendations have explicit Python 3 support. By “explicit” I mean “not accidental”: I looked for the “supported Python” package metadata, inclusion it in the test suite, or mentioning it in the Readme.

Image file format exporters

The task of rendering a string of text into a barcode of a certain symbology consists of two steps: First, figure out what lines (or squares or circles or other geometric artifacts) represent the given text (or number or URL or other content). Second, exporting the lines in an image file format such as PNG, JPG, or SVG.

You’ll find a Python package to generate each of the common image file formats, but many of them contain C code. The Pillow project is a bundle of many such packages and provide one consistent API for many image file formats, but can still prove troublesome to install.

Thanks to wheels and conda, installing Python packages is less thorny than the war stories in 2013 StackOverflow results would make you think. Nonetheless, it remains a common stumbling block, especially for Windows users, which is why I consider a dependency on Pillow a downside in this review.

Ease of installation is a natural side effect of any Python package that is itself written in self-contained pure Python, i.e. without any embedded C code or external dependencies. The pypng package is a pure Python implementation of the PNG file format. The SVG file format is an XML document type and therefore plain text and easily generated from pure Python.

A reasonable in-between solution is offered by several packages that support a limited set of formats in the default installation and expanded capabilities if Pillow happens to be independently installed.

The segno package for QR codes deserves a mention for supporting nine outputs formats without relying on any external dependency.

Notes about the Contenders

For anyone still reading, this section contains a collection of marginally interesting notes I scribbled down while researching the packages covered in this review.

pyBarcode and its forks

The genealogy of the pyBarcode family is a fascinating story for every code archeologist. For several years, pyBarcode was the only game in town for generating barcodes in Python and there was a steady trickle of features and version releases. When this stopped 2013, two forks gained some tractions by releasing their own version 0.8: python-barcode and viivakoodi (“barcode” in Finnish). The former has received a handful of bugfix and maintance releases including, most recently, “official” Python 3.7 support and is my second recommendation at the top of this article. viivakoodi fizzled out in 2014 and sparked further forks, none of which have recent updates. In addition to those that became PyPI packages, Github has tens of other forks, each with their own independent bug fixes. Oh open source.

PyPI historians will not want to miss a final (?) plot twist in 2017: Suddenly there was a new pre-release version of pyBarcode! Sadly, it has stayed a pre-release since then. As, sadly, usual for dormant open source code, the lack of activity does not deter people from filling the issue tracker and demanding fixes and new features from the solo maintainer.

code128, PubCode

Most small open source projects eventually go dormant, but some maintainers actively delete their work. This is what happened to code128. The latest version on PyPI is 0.3 from 2015. There are indications that development continued after that date, but the source code disappeared and remains gone.

Based on features alone, I have a preference for code128 over PubCode due to Pillow being optional, but in absence of code or maintenance cannot recommend the package.

qrcode, PyQRCode, qrcodegen, segno

qrcode is the only package in the comparison table that can credibly claim to be “popular”. 1,639 have “stared” the repository on Github and there is regular activity in the issue tracker. It probably helps that this package is maintained by a company and not an individual’s side project like most others in the comparison table. If your need happens to be for standard QR Codes, you should choose this package. However, it doesn’t make the list of recommendations at the top of the article because segno additionally supports Micro QR codes.

segno’s documentation has a much more detailed comparison of QR Code generators, including some in-the-weeds comparison criteria I don’t fully understand.

libdmtx, pydmtx, pylibdmtx

pydmtx is part of the main libdmtx codebase. The maintenance status of this project is unclear to me: There have been no updates since 2009 but recently the project has been migrated from Sourceforge to Github. pylibdmtx updates pydmtx to support Python 3 and includes the dll in the Windows wheel but requires a separate install of libdmtx on all other platforms which is why it is my recommendation for generating Datamatrix codes.

More about Barcodes

The content of this article was part of my talk “Zebras & Lasers” at PyBay 2018. Slide deck and video from the talk are here.

Other posts about barcodes on my blog: