ExifRead Library
ExifRead is a Python library designed to extract Exif metadata from digital camera image files, including JPEG, TIFF, and HEIC/HEIF formats. It provides a straightforward API to access various EXIF tags, maker notes, and thumbnails. The library is actively maintained, with frequent minor releases (typically monthly or bi-monthly) to add support for new camera models, file formats, and address bug fixes. The current version is 3.5.1.
Warnings
- breaking Python 2.x compatibility was removed in version 3.0.0. Python 3.5 and 3.6 support was dropped in version 3.1.0. Users on older Python versions must use an older `exifread` version.
- gotcha Accessing EXIF tags by dictionary key (e.g., `tags['Tag Name']`) will raise a `KeyError` if the tag does not exist in the image's metadata. Not all images contain all possible EXIF tags.
- gotcha The values returned from `exifread.process_file` are `IFD_Tag` objects, not raw strings or numbers. To get a human-readable string representation, you typically need to access the `.printable` attribute. Other attributes like `.values`, `.num`, `.den` provide raw data.
- gotcha By default (`strict=True`), `exifread.process_file` can raise exceptions for malformed or non-standard maker notes, especially with some camera models. Version 3.5.1 fixed an issue where `strict=False` wasn't always honored.
Install
-
pip install exifread
Imports
- exifread
import exifread
Quickstart
import exifread
import os
# Create a dummy image file for demonstration
# In a real scenario, you'd open an existing image.
# For a runnable example, we'll create a placeholder that can be opened.
# This will likely fail to extract *real* EXIF but demonstrates the API.
with open('dummy_image.jpg', 'wb') as f:
f.write(b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c\x20"!\22\"\22\x15\x15\x20\x2f\x36\x28\x30\x3d\x30\x28\x2c\x32\x34\x34\x34\x1f\x27\x39\x3d\x38\x32\x3c\x2e\x33\x34\x30\xff\xc0\x00\x11\x08\x00\x01\x00\x01\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x11\x01\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaahundred_times\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00\x3f\x00\xd2\xcf\x20\xff\xd9')
image_path = 'dummy_image.jpg'
try:
with open(image_path, 'rb') as f:
tags = exifread.process_file(f, strict=False)
if tags:
print(f"EXIF data for {image_path}:")
for tag_name, tag_value in tags.items():
# Filter for some common tags
if tag_name not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'):
print(f" {tag_name}: {tag_value}")
# Access a specific tag, handling potential KeyError
if 'EXIF DateTimeOriginal' in tags:
print(f"\nOriginal Date/Time: {tags['EXIF DateTimeOriginal'].printable}")
else:
print("\n'EXIF DateTimeOriginal' tag not found.")
else:
print(f"No EXIF data found in {image_path}.")
except FileNotFoundError:
print(f"Error: File not found at {image_path}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up the dummy file
if os.path.exists(image_path):
os.remove(image_path)