Skip to content

Instantly share code, notes, and snippets.

@godber
Last active July 4, 2023 13:21
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save godber/7692812 to your computer and use it in GitHub Desktop.
pdfinfo - A simple python wrapper of the pdfinfo command line tool.

PDFINFO example

Wraps command line utility pdfinfo to extract the PDF meta information. The PDF meta information is returned in a dictionary.

  • LICENSE and AUTHOR file added
  • This has now been modified to work with either Python 2 or Python 3.
  • An example has been added, see example.py.
python ./example.py
{'Tagged': 'no', 'Producer': 'Mac OS X 10.12.1 Quartz PDFContext', 'Creator': 'Word', 'Encrypted': 'no', 'Author': 'Shekhar Vemuri', 'File size': '6264512 bytes', 'Optimized': 'no', 'PDF version': '1.3', 'ModDate': 'Thu Dec  8 11:42:16 2016 MST', 'Title': 'Guide to Apache Airflow', 'Page size': '612 x 792 pts (letter)', 'CreationDate': 'Thu Dec  8 11:42:16 2016 MST', 'Pages': '6'}

Dependencies

This script assumes that the pdfinfo command line command is available at /usr/bin/pdfinfo.
On debian like Linux, you can install that like this:

sudo apt-get install poppler-utils

The poppler package appears to be present on MacOS via brew so this script could be adapted to work on MacOS as well. Though there's almost certainly a better way of getting this info with a native Python PDF package.

Details

This function parses the text output that looks like this:

        Title:          PUBLIC MEETING AGENDA
        Author:         Customer Support
        Creator:        Microsoft Word 2010
        Producer:       Microsoft Word 2010
        CreationDate:   Thu Dec 20 14:44:56 2012
        ModDate:        Thu Dec 20 14:44:56 2012
        Tagged:         yes
        Pages:          2
        Encrypted:      no
        Page size:      612 x 792 pts (letter)
        File size:      104739 bytes
        Optimized:      no
        PDF version:    1.5
Austin Godber - godber@uberhip.com
from pdfinfo import pdfinfo
i = pdfinfo("/tmp/GuideToApacheAirflow.pdf")
print(i)
BSD 3-Clause License
Copyright (c) 2019-2022, the respective contributors, as shown by the AUTHORS file.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import subprocess
import os.path as osp
def pdfinfo(infile):
"""
Wraps command line utility pdfinfo to extract the PDF meta information.
Returns metainfo in a dictionary.
sudo apt-get install poppler-utils
This function parses the text output that looks like this:
Title: PUBLIC MEETING AGENDA
Author: Customer Support
Creator: Microsoft Word 2010
Producer: Microsoft Word 2010
CreationDate: Thu Dec 20 14:44:56 2012
ModDate: Thu Dec 20 14:44:56 2012
Tagged: yes
Pages: 2
Encrypted: no
Page size: 612 x 792 pts (letter)
File size: 104739 bytes
Optimized: no
PDF version: 1.5
"""
cmd = '/usr/bin/pdfinfo'
if not osp.exists(cmd):
raise RuntimeError('System command not found: %s' % cmd)
if not osp.exists(infile):
raise RuntimeError('Provided input file not found: %s' % infile)
def _extract(row):
"""Extracts the right hand value from a : delimited row"""
return row.split(':', 1)[1].strip()
output = {}
labels = ['Title', 'Author', 'Creator', 'Producer', 'CreationDate',
'ModDate', 'Tagged', 'Pages', 'Encrypted', 'Page size',
'File size', 'Optimized', 'PDF version']
cmd_output = subprocess.check_output([cmd, infile])
for line in map(str, cmd_output.splitlines()):
for label in labels:
if label in line:
output[label] = _extract(line)
return output
@godber
Copy link
Author

godber commented Nov 28, 2013

_extract updated to handle the CreationDate and ModDate fields.

@ronan-mch
Copy link

This is great thanks. Note that it requires Python 2.7 or higher as subprocess.check_output does not exist before then. For those stuck on previous versions (CentOS users for example), you can use the workaround from this StackOverflow example i.e cmd_output = subprocess.Popen([cmd, infile], stdout=subprocess.PIPE).communicate()[0].

@laentropia
Copy link

laentropia commented Oct 3, 2019

Hi, @godber,
I'm trying to use your code, but I got a weird error.

Traceback (most recent call last):
File "pdfparser.py", line 7, in
pdfinfo("/tmp/GuideToApacheAirflow.pdf")
File "/home/borja/Escritorio/pdfiinfo.py", line 45, in pdfinfo
if label in line:
TypeError: a bytes-like object is required, not 'str'

It says the pdf path to the file to retrieve info should be a bytes-like object. But check_output() receive a pair of strings.

Best

@laentropia
Copy link

laentropia commented Oct 3, 2019

My solution is:

for line in cmd_output.splitlines():
for label in labels:
if label in srt(line):
output[label] = _extract(str(line))

Only do a cast of lines to str()...
It works for me

@godber
Copy link
Author

godber commented Oct 3, 2019

Probably a python 2 versus python 3 thing. I'll make the change.

@godber
Copy link
Author

godber commented Oct 3, 2019

I made a few changes, it now works in python 2.7 (which is EOL in 3 months) and python 3. I was missing the subprocess import. I moved the imports outside the function definition. I mapped the subprocess output to strings. Oh, I renamed the file from pdfiinfo.py to pdfinfo.py.

@pankajthekush
Copy link

Hi, this works amazing, can you add license attributions to it, so that I can use this in my project

@godber
Copy link
Author

godber commented Oct 14, 2022

@pankajthekush , thanks for the feedback, I am glad you found this useful. I honestly can't even remember why I made this, but I have added a LICENSE and AUTHORS file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment