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

core-interface.mddocs/

Core Interface

Low-level interface to the exiftool subprocess providing direct command execution, JSON parsing, and subprocess lifecycle management. The ExifTool class offers maximum control and flexibility for advanced users who need fine-grained control over the exiftool process.

Capabilities

Process Management

Control the exiftool subprocess lifecycle with start, stop, and context manager support.

class ExifTool:
    def __init__(self, executable=None, common_args=["-G", "-n"], win_shell=False, config_file=None, encoding=None, logger=None):
        """
        Initialize ExifTool instance.

        Parameters:
        - executable: str or Path, path to exiftool executable (default: searches PATH)
        - common_args: list of str, arguments included in every command (default: ["-G", "-n"])
        - win_shell: bool, Windows shell visibility (default: False)
        - config_file: str or Path, path to exiftool config file
        - encoding: str, text encoding for subprocess communication (default: utf-8)
        - logger: logger instance for debug output
        """

    def run(self):
        """
        Start the exiftool subprocess in batch mode.
        
        Raises:
        - ExifToolRunning: if subprocess is already running
        - Various subprocess errors if startup fails
        """

    def terminate(self, timeout=30, _del=False):
        """
        Terminate the exiftool subprocess.
        
        Parameters:
        - timeout: int, seconds to wait for clean shutdown (default: 30)
        - _del: bool, internal flag for destructor cleanup
        """

    def __enter__(self):
        """Context manager entry - automatically calls run()"""

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit - automatically calls terminate()"""

    def __del__(self):
        """Destructor - automatically terminates subprocess if still running"""

Command Execution

Execute exiftool commands directly with raw output or JSON parsing.

def execute(self, *params, raw_bytes=False):
    """
    Execute parameters with the exiftool subprocess.
    
    Parameters:
    - *params: str or bytes, command parameters to send to exiftool
    - raw_bytes: bool, return bytes instead of str (default: False)
    
    Returns:
    str or bytes: command stdout output
    
    Raises:
    - ExifToolNotRunning: if subprocess is not running
    - ExifToolVersionError: if version compatibility issues
    - TypeError: if parameter types are invalid
    """

def execute_json(self, *params):
    """
    Execute parameters and parse JSON output.
    
    Parameters:
    - *params: str or bytes, command parameters to send to exiftool
    
    Returns:
    list: parsed JSON as list of dictionaries
    
    Raises:
    - ExifToolOutputEmptyError: if no output received when expected
    - ExifToolJSONInvalidError: if invalid JSON received
    """

Configuration

Configure the ExifTool instance behavior and access runtime information.

# Properties (read/write)
@property
def executable(self) -> Union[str, Path]:
    """Path to exiftool executable (can only be set when not running)"""

@property  
def encoding(self) -> str:
    """Text encoding for subprocess communication (can only be set when not running)"""

@property
def block_size(self) -> int:
    """Block size for reading from subprocess pipes (default: 4096)"""

@property
def common_args(self) -> List[str]:
    """Common arguments included in every command (can only be set when not running)"""

@property
def config_file(self) -> Union[str, Path]:
    """Path to exiftool config file (can only be set when not running)"""

# Properties (read-only)
@property
def running(self) -> bool:
    """Whether the exiftool subprocess is currently running"""

@property
def version(self) -> str:
    """Version string of the running exiftool process (only available when running)"""

@property
def last_stdout(self) -> Union[str, bytes]:
    """STDOUT from most recent execute() call"""

@property
def last_stderr(self) -> Union[str, bytes]:
    """STDERR from most recent execute() call"""

@property
def last_status(self) -> int:
    """Exit status code from most recent execute() call"""

# Properties (write-only)
@property
def logger(self):
    """Set logger instance for debug output"""

JSON Customization

Override the default JSON parser for performance or compatibility.

def set_json_loads(self, json_loads, **kwargs):
    """
    Override default JSON parser method.
    
    Parameters:
    - json_loads: callable, alternative JSON loading function (e.g., ujson.loads)
    - **kwargs: additional arguments passed to the JSON loader
    """

Usage Examples

Basic Process Control

import exiftool

# Manual process control
et = exiftool.ExifTool()
et.run()
try:
    result = et.execute('-ver')
    print(f"ExifTool version: {result}")
finally:
    et.terminate()

# Context manager (recommended)
with exiftool.ExifTool() as et:
    result = et.execute('-ver')
    print(f"ExifTool version: {result}")

Direct Command Execution

with exiftool.ExifTool() as et:
    # Get basic info
    output = et.execute('-n', '-g', 'image.jpg')
    
    # Get JSON output
    metadata = et.execute_json('-j', 'image.jpg')
    
    # Set tags
    et.execute('-overwrite_original', '-EXIF:Artist=John Doe', 'image.jpg')

Custom JSON Parser

import ujson
import exiftool

with exiftool.ExifTool() as et:
    # Use ujson for better performance
    et.set_json_loads(ujson.loads)
    metadata = et.execute_json('-j', 'large_file.jpg')

Configuration Example

import exiftool

# Custom configuration
et = exiftool.ExifTool(
    executable='/usr/local/bin/exiftool',
    common_args=['-G', '-n', '-q'],  # Add quiet flag
    encoding='utf-8',
    config_file='my_exiftool.config'
)

with et:
    # All commands will include common_args
    result = et.execute('image.jpg')  # Equivalent to: exiftool -G -n -q image.jpg

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