PyExifTool
PyExifTool provides a convenient Python interface to Phil Harvey's ExifTool, a powerful command-line application for reading, writing, and editing metadata in a wide variety of file formats. The current version is 0.5.6, and it maintains an active release cadence with new features and improvements.
Common errors
-
FileNotFoundError: [Errno 2] No such file or directory: 'exiftool'
cause The `exiftool` command-line utility is not installed on your system or is not located in a directory listed in your system's PATH environment variable.fixInstall `exiftool` using your operating system's package manager (e.g., `sudo apt install libimage-exiftool-perl` on Debian/Ubuntu, `brew install exiftool` on macOS) or download it from `exiftool.org` and ensure it's in your PATH. -
AttributeError: 'ExifTool' object has no attribute 'get_tag' (or 'set_tag')
cause Your code is likely using an older API pattern (from v0.4.x) that is incompatible with PyExifTool v0.5.x and later, which underwent a major refactor.fixUpdate your code to use the new API methods such as `et.get_metadata(filename)` to read tags and `et.set_tags(tags_dict, [filename])` to write tags. Refer to the current documentation. -
pyexiftool.exceptions.ExifToolProcessStateError: Process is not running. Call start() or use a context manager.
cause An `ExifTool` instance was used without explicitly starting the underlying `exiftool` process or without using a context manager (`with ExifTool() as et:`).fixAlways use `ExifTool` within a `with` statement (`with ExifTool() as et:`), which handles starting and terminating the process automatically, or manually call `et.start()` before use and `et.terminate()` afterwards. -
AttributeError: 'ExifTool' object has no attribute 'set_json_library'
cause Prior to v0.5.6, `pyexiftool` allowed setting a custom JSON library via `set_json_library()`. This method was removed, and the mechanism changed in v0.5.6.fixIf you need to customize JSON parsing (e.g., to use `ujson`), use the new `ExifTool.set_json_loads(custom_loads_function)` method introduced in v0.5.6. The auto-detection of `ujson` was also removed, requiring explicit configuration.
Warnings
- breaking PyExifTool v0.5.0 introduced a major refactor, breaking compatibility with previous 0.4.x versions. It requires Python 3.6+ and exiftool 12.15+.
- gotcha The `exiftool` command-line utility must be separately installed and available in your system's PATH. PyExifTool is a wrapper and does not bundle it.
- breaking Starting with v0.5.6, `ujson` is no longer automatically used for JSON parsing when available. You must explicitly configure it if you want to use a custom JSON library or `ujson`.
- deprecated PyExifTool ended Python 2 support with v0.4.13. All versions 0.5.0 and later require Python 3.6+.
- breaking Error class names were renamed in v0.5.3 to be more explicit (e.g., `ProcessStateError` became `ExifToolProcessStateError`).
- gotcha The `ExifToolHelper` class (introduced in v0.5.2) now checks the `exiftool` subprocess exit status by default and raises `ExifToolExecuteError` on non-zero status. This can change behavior for scripts expecting silent failures.
Install
-
pip install pyexiftool
Imports
- ExifTool
from pyexiftool import ExifTool
- ExifToolHelper
from pyexiftool import ExifToolHelper
Quickstart
import os
from pyexiftool import ExifTool
# IMPORTANT: Ensure the 'exiftool' command-line utility is installed
# and accessible on your system PATH.
# For Debian/Ubuntu: sudo apt-get install libimage-exiftool-perl
# For macOS: brew install exiftool
# More info: https://exiftool.org/
# Create a dummy image file for demonstration if it doesn't exist
image_file = "example.jpg"
if not os.path.exists(image_file):
with open(image_file, "w") as f:
f.write("Simulated JPEG content\n")
print(f"Created dummy file: {image_file}. Replace with a real image for meaningful EXIF data.")
try:
# Use ExifTool as a context manager to ensure proper process handling
with ExifTool() as et:
# Read all metadata from the image file
metadata = et.get_metadata(image_file)
print(f"\nMetadata for {image_file}:")
for tag, value in metadata.items():
print(f" {tag}: {value}")
# Example of writing metadata (uncomment and use a real image if needed)
# For writing, ensure the image_file is a real image and you have write permissions.
# new_tags = {"Exif.Image.Artist": "Python Bot", "Exif.Image.Copyright": "2023 Example Corp"}
# et.set_tags(new_tags, [image_file])
# print(f"\nUpdated metadata for {image_file}")
# updated_metadata = et.get_metadata(image_file)
# print("Updated Artist:", updated_metadata.get("Exif.Image.Artist"))
except Exception as e:
print(f"An error occurred: {e}")
print("Please ensure 'exiftool' is installed and your image file path is correct.")
finally:
# Clean up the dummy file if it was created
if os.path.exists(image_file) and os.path.getsize(image_file) == len("Simulated JPEG content\n"):
os.remove(image_file)
print(f"Cleaned up dummy file: {image_file}")