CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyexiftool

Python wrapper for exiftool to extract and manipulate metadata from image, video, and other media files

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

exception-handling.mddocs/

Exception Handling

PyExifTool provides a comprehensive exception hierarchy for different error conditions with detailed error information including exit codes, command output, and specific error contexts. All exceptions inherit from the base ExifToolException class for easy catch-all error handling.

Capabilities

Base Exception Classes

Foundation exception classes that provide common interfaces and are never raised directly.

class ExifToolException(Exception):
    """
    Generic base class for all ExifTool error classes.
    Use this for catch-all exception handling.
    """

class ExifToolProcessStateError(ExifToolException):
    """
    Base class for all errors related to invalid state of exiftool subprocess.
    Covers scenarios where subprocess is running when it shouldn't be or vice versa.
    """

class ExifToolExecuteException(ExifToolException):
    """
    Base exception class for all execute() associated errors.
    Never returned directly but provides common interface for subclassed errors.
    
    Attributes:
    - returncode: int, exit status from exiftool command
    - cmd: list, parameters sent to exiftool that caused error
    - stdout: str, STDOUT stream from failed command
    - stderr: str, STDERR stream from failed command
    """
    
    def __init__(self, message, exit_status, cmd_stdout, cmd_stderr, params):
        """
        Initialize execute exception with detailed error context.
        
        Parameters:
        - message: str, error description
        - exit_status: int, command exit status
        - cmd_stdout: str, command stdout output
        - cmd_stderr: str, command stderr output  
        - params: list, command parameters that failed
        """

Process State Exceptions

Exceptions raised when subprocess operations are attempted in invalid states.

class ExifToolRunning(ExifToolProcessStateError):
    """
    Raised when trying to modify settings while subprocess is running.
    Common scenarios: changing executable path, encoding, or common_args while running.
    """
    
    def __init__(self, message: str):
        """
        Initialize with descriptive message.
        
        Parameters:
        - message: str, description of what operation was attempted
        """

class ExifToolNotRunning(ExifToolProcessStateError):
    """
    Raised when trying to execute commands while subprocess is not running.
    Common scenarios: calling execute() before run() or after terminate().
    """
    
    def __init__(self, message: str):
        """
        Initialize with descriptive message.
        
        Parameters:
        - message: str, description of what operation was attempted
        """

Execute Exceptions

Exceptions raised during command execution with detailed error information.

class ExifToolExecuteError(ExifToolExecuteException):
    """
    Raised when execute() returns non-zero exit status.
    Most common execution error - indicates exiftool command failed.
    """
    
    def __init__(self, exit_status, cmd_stdout, cmd_stderr, params):
        """
        Initialize with command execution details.
        
        Parameters:
        - exit_status: int, non-zero exit status from exiftool
        - cmd_stdout: str, stdout from failed command
        - cmd_stderr: str, stderr from failed command
        - params: list, command parameters that failed
        """

class ExifToolOutputEmptyError(ExifToolExecuteException):
    """
    Raised when execute_json() expects output but execute() returns none.
    Indicates mismatch between expected JSON output and actual command behavior.
    """
    
    def __init__(self, exit_status, cmd_stdout, cmd_stderr, params):
        """
        Initialize with empty output context.
        
        Parameters:
        - exit_status: int, command exit status
        - cmd_stdout: str, empty stdout that was expected to contain JSON
        - cmd_stderr: str, stderr output
        - params: list, command parameters that produced no output
        """

class ExifToolJSONInvalidError(ExifToolExecuteException):
    """
    Raised when execute_json() receives invalid JSON from exiftool.
    Indicates JSON parsing failure of exiftool output.
    """
    
    def __init__(self, exit_status, cmd_stdout, cmd_stderr, params):
        """
        Initialize with invalid JSON context.
        
        Parameters:
        - exit_status: int, command exit status
        - cmd_stdout: str, stdout containing invalid JSON
        - cmd_stderr: str, stderr output
        - params: list, command parameters that produced invalid JSON
        """

Other Exceptions

Specialized exceptions for specific error conditions.

class ExifToolVersionError(ExifToolException):
    """
    Raised when exiftool version requirements are not met.
    PyExifTool requires exiftool version 12.15 or later for full functionality.
    """

class ExifToolTagNameError(ExifToolException):
    """
    Raised when invalid tag names are detected by ExifToolHelper.
    Only occurs when check_tag_names is enabled and invalid tag format is found.
    """
    
    def __init__(self, bad_tag):
        """
        Initialize with invalid tag name.
        
        Parameters:
        - bad_tag: str, the invalid tag name that was detected
        """

Usage Examples

Basic Exception Handling

import exiftool
from exiftool.exceptions import ExifToolException, ExifToolExecuteError

try:
    with exiftool.ExifToolHelper() as et:
        metadata = et.get_metadata('nonexistent.jpg')
except ExifToolExecuteError as e:
    print(f"Command failed with exit status {e.returncode}")
    print(f"Error output: {e.stderr}")
    print(f"Command: {' '.join(e.cmd)}")
except ExifToolException as e:
    print(f"ExifTool error: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")

Specific Exception Handling

from exiftool.exceptions import (
    ExifToolNotRunning, 
    ExifToolRunning,
    ExifToolJSONInvalidError,
    ExifToolTagNameError
)

et = exiftool.ExifTool()

try:
    # This will raise ExifToolNotRunning
    et.execute('-ver')
except ExifToolNotRunning as e:
    print(f"Need to start subprocess first: {e}")
    et.run()

try:
    # This might raise ExifToolJSONInvalidError
    result = et.execute_json('-invalid-json-command')
except ExifToolJSONInvalidError as e:
    print(f"JSON parsing failed: {e}")
    print(f"Raw output was: {e.stdout}")

try:
    # This will raise ExifToolRunning
    et.executable = '/different/path/exiftool'
except ExifToolRunning as e:
    print(f"Cannot change settings while running: {e}")

et.terminate()

Helper Class Exception Handling

from exiftool.exceptions import ExifToolTagNameError

with exiftool.ExifToolHelper(check_tag_names=True) as et:
    try:
        # This will raise ExifToolTagNameError if tag format is invalid
        et.get_tags('photo.jpg', ['Invalid:Tag:Format'])
    except ExifToolTagNameError as e:
        print(f"Invalid tag name: {e}")
        
    try:
        # Disable tag checking for this operation
        et.check_tag_names = False
        et.get_tags('photo.jpg', ['Invalid:Tag:Format'])  # Won't raise error
    except ExifToolExecuteError as e:
        print(f"Command failed at exiftool level: {e}")

Comprehensive Error Handling Pattern

import exiftool
from exiftool.exceptions import (
    ExifToolException,
    ExifToolProcessStateError, 
    ExifToolExecuteException,
    ExifToolExecuteError,
    ExifToolVersionError
)

def safe_get_metadata(file_paths):
    """
    Safely extract metadata with comprehensive error handling.
    """
    try:
        with exiftool.ExifToolHelper() as et:
            return et.get_metadata(file_paths)
            
    except ExifToolVersionError as e:
        print(f"ExifTool version incompatible: {e}")
        print("Please update to exiftool 12.15 or later")
        return None
        
    except ExifToolExecuteError as e:
        print(f"Command execution failed:")
        print(f"  Exit status: {e.returncode}")
        print(f"  Command: {' '.join(e.cmd)}")
        if e.stderr:
            print(f"  Error: {e.stderr}")
        return None
        
    except ExifToolProcessStateError as e:
        print(f"Subprocess state error: {e}")
        return None
        
    except ExifToolException as e:
        print(f"ExifTool library error: {e}")
        return None
        
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None

# Usage
metadata = safe_get_metadata(['photo1.jpg', 'photo2.png'])
if metadata:
    for data in metadata:
        print(f"Successfully processed: {data['SourceFile']}")

Error Information Extraction

from exiftool.exceptions import ExifToolExecuteException

try:
    with exiftool.ExifTool() as et:
        et.execute('-invalid-option', 'file.jpg')
except ExifToolExecuteException as e:
    # Access detailed error information
    print(f"Command that failed: {' '.join(e.cmd)}")
    print(f"Exit code: {e.returncode}")
    print(f"Standard output: {e.stdout}")
    print(f"Error output: {e.stderr}")
    
    # Error information can be used for logging or debugging
    error_details = {
        'command': e.cmd,
        'exit_code': e.returncode,
        'stdout': e.stdout,
        'stderr': e.stderr,
        'error_type': type(e).__name__
    }
    print(f"Error details: {error_details}")

Install with Tessl CLI

npx tessl i tessl/pypi-pyexiftool

docs

core-interface.md

exception-handling.md

experimental-features.md

helper-interface.md

index.md

tile.json