Python wrapper for exiftool to extract and manipulate metadata from image, video, and other media files
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
User-friendly wrapper around the core ExifTool class that adds convenience methods for common metadata operations, automatic error checking, and simplified file handling. The ExifToolHelper class is recommended for most users as it provides a cleaner API while maintaining access to all core functionality.
Enhanced initialization with helper-specific features and automatic process management.
class ExifToolHelper(ExifTool):
def __init__(self, auto_start=True, check_execute=True, check_tag_names=True, **kwargs):
"""
Initialize ExifToolHelper with enhanced features.
Parameters:
- auto_start: bool, automatically start subprocess on first command (default: True)
- check_execute: bool, check exit status of commands and raise errors (default: True)
- check_tag_names: bool, validate tag name format before execution (default: True)
- **kwargs: additional arguments passed to ExifTool constructor
"""
@property
def auto_start(self) -> bool:
"""Whether auto-start is enabled (read-only)"""
@property
def check_execute(self) -> bool:
"""Whether to check command exit status (read/write)"""
@property
def check_tag_names(self) -> bool:
"""Whether to validate tag names (read/write)"""Process control methods with improved error handling and auto-start capability.
def run(self):
"""
Start subprocess without warnings if already running.
Enhanced version of ExifTool.run() with better error handling.
"""
def terminate(self, **opts):
"""
Terminate subprocess without warnings if not running.
Enhanced version of ExifTool.terminate() with better error handling.
Parameters:
- **opts: options passed to parent terminate() method
"""
def execute(self, *params, **kwargs):
"""
Enhanced execute with auto-start and error checking.
Parameters:
- *params: command parameters (same as ExifTool.execute)
- **kwargs: additional options (same as ExifTool.execute)
Returns:
str or bytes: command output
Raises:
- ExifToolExecuteError: if check_execute enabled and command returns non-zero exit status
"""High-level methods for common metadata extraction and manipulation tasks.
def get_metadata(self, files, params=None):
"""
Get all metadata for specified files.
Parameters:
- files: str or list, file path(s) to process
- params: str, list, or None, optional exiftool parameters
Returns:
list: list of metadata dictionaries, one per file
Raises:
- ValueError: if files parameter is empty
- ExifToolExecuteError: if command fails
"""
def get_tags(self, files, tags, params=None):
"""
Get specific tags from files.
Parameters:
- files: str or list, file path(s) to process
- tags: str, list, or None, tag name(s) to retrieve (None for all tags)
- params: str, list, or None, optional exiftool parameters
Returns:
list: list of tag dictionaries, one per file
Raises:
- ValueError: if files parameter is empty
- TypeError: if parameters have incorrect types
- ExifToolTagNameError: if check_tag_names enabled and invalid tag names found
- ExifToolExecuteError: if command fails
"""
def set_tags(self, files, tags, params=None):
"""
Set tag values on files.
Parameters:
- files: str or list, file path(s) to modify
- tags: dict, mapping of tag names to values
- params: str, list, or None, optional exiftool parameters
Returns:
str: command output from exiftool
Raises:
- ValueError: if files parameter is empty or tags is not a dict
- TypeError: if parameters have incorrect types
- ExifToolTagNameError: if check_tag_names enabled and invalid tag names found
- ExifToolExecuteError: if command fails
"""Static methods for parameter validation and processing.
@staticmethod
def _parse_arg_files(files):
"""
Parse files argument into list format.
Parameters:
- files: str or list, files parameter from user
Returns:
list: list of file strings
Raises:
- ValueError: if files is empty
"""
@staticmethod
def _check_tag_list(tags):
"""
Validate tag names using regex pattern.
Parameters:
- tags: list, list of tag names to check
Raises:
- ExifToolTagNameError: for invalid tag names
"""import exiftool
files = ['photo1.jpg', 'photo2.png', 'video.mp4']
with exiftool.ExifToolHelper() as et:
# Get all metadata
metadata = et.get_metadata(files)
for data in metadata:
print(f"File: {data['SourceFile']}")
if 'EXIF:DateTimeOriginal' in data:
print(f"Date taken: {data['EXIF:DateTimeOriginal']}")
if 'EXIF:Make' in data:
print(f"Camera: {data['EXIF:Make']} {data.get('EXIF:Model', '')}")
print()with exiftool.ExifToolHelper() as et:
# Get specific tags only
camera_tags = ['EXIF:Make', 'EXIF:Model', 'EXIF:LensModel', 'EXIF:FocalLength']
camera_info = et.get_tags(files, camera_tags)
for info in camera_info:
print(f"File: {info['SourceFile']}")
print(f"Camera: {info.get('EXIF:Make', 'Unknown')} {info.get('EXIF:Model', '')}")
print(f"Lens: {info.get('EXIF:LensModel', 'Unknown')}")
print(f"Focal Length: {info.get('EXIF:FocalLength', 'Unknown')}")
print()with exiftool.ExifToolHelper() as et:
# Set single file tags
et.set_tags('photo.jpg', {
'EXIF:Artist': 'John Doe',
'EXIF:Copyright': '© 2023 John Doe',
'IPTC:Keywords': ['landscape', 'nature', 'photography']
})
# Set tags on multiple files
et.set_tags(['photo1.jpg', 'photo2.jpg'], {
'EXIF:Artist': 'Jane Smith'
})# Initialize with custom settings
with exiftool.ExifToolHelper(
check_execute=True, # Raise errors on command failures
check_tag_names=True, # Validate tag names before execution
auto_start=True, # Auto-start subprocess on first command
common_args=['-G', '-n', '-q'] # Custom common arguments
) as et:
metadata = et.get_metadata('image.jpg')with exiftool.ExifToolHelper() as et:
# Disable error checking for non-critical operations
et.check_execute = False
result = et.execute('-this-might-fail', 'file.jpg')
# Re-enable for critical operations
et.check_execute = True
metadata = et.get_metadata('important.jpg') # Will raise on errorswith exiftool.ExifToolHelper() as et:
# Use additional exiftool parameters
metadata = et.get_metadata(
files=['image1.jpg', 'image2.tiff'],
params=['-c', '%.6f'] # High precision GPS coordinates
)
# Get tags with custom formatting
tags = et.get_tags(
files='photo.jpg',
tags=['EXIF:CreateDate', 'EXIF:ISO'],
params=['-d', '%Y-%m-%d %H:%M:%S'] # Custom date format
)Install with Tessl CLI
npx tessl i tessl/pypi-pyexiftool