Examples / Quick Start

Try it yourself: All of these examples are using the images provided in the tests directory in the source

Understanding input and output from PyExifTool base methods

Almost all methods in PyExifTool revolve around the usage of two methods from the base exiftool.ExifTool class.

It is important to understand the ouput from each of these commands, so here’s a quick summary (you can click through to the API to read more details)

Note

Because both methods are inherited by exiftool.ExifToolHelper and exiftool.ExifToolAlpha, you can call it from those classes as well.

Input parameters

Both methods take an argument list *args. Examples:

Note

As a general rule of thumb, if there is an unquoted space on the command line to exiftool, it’s a separate argument to the method in PyExifTool.

If you have a working exiftool command-line but having trouble figuring out how to properly separate the arguments, please refer to the FAQ

  • Calling directly:

    • exiftool command-line:

      exiftool -XMPToolKit -Subject rose.jpg
      
    • PyExifTool:

      execute("-XMPToolKit", "-Subject", "rose.jpg")
      
  • Using argument unpacking of a list:

    • exiftool command-line:

      exiftool -P -DateTimeOriginal="2021:01:02 03:04:05" -MakerNotes= "spaces in filename.jpg"
      
    • PyExifTool:

      Note

      Parameters which need to be quoted on the command line generally do not need to be quoted in the parameters to PyExifTool. In fact, quoting may have unintended behavior.

      In this example, DateTimeOriginal value is not quoted in the parameter to execute().

      execute(*["-P", "-DateTimeOriginal=2021:01:02 03:04:05", "-MakerNotes=", "spaces in filename.jpg"])
      
  • Getting JSON output using argument unpacking of a list:

    • exiftool command-line:

      exiftool -j -XMP:all -JFIF:JFIFVersion /path/somefile.jpg
      
    • PyExifTool:

      execute_json(*["-XMP:all", "-JFIF:JFIFVersion", "/path/somefile.jpg"])
      

Output values

  • exiftool.ExifTool.execute_json()

    • Returns a list of dict

    • Each dict is a result from a file

    • Each dict contains a key “SourceFile” which points to the relative or absolute file path of file

    • All other keys/value pairs are requested metadata

  • exiftool.ExifTool.execute()

    • Returns a str

    • Typically used for setting tags as no values are returned in that case.

ExifToolHelper

Using methods provided by exiftool.ExifToolHelper:

ExifToolHelper provides some of the most commonly used operations most people use exiftool for

Getting Tags

  • Get all tags on a single file

    from exiftool import ExifToolHelper
    with ExifToolHelper() as et:
        for d in et.get_metadata("rose.jpg"):
            for k, v in d.items():
                print(f"Dict: {k} = {v}")
    
    Dict: SourceFile = rose.jpg
    Dict: ExifTool:ExifToolVersion = 12.37
    Dict: File:FileName = rose.jpg
    Dict: File:Directory = .
    Dict: File:FileSize = 4949
    Dict: File:FileModifyDate = 2022:03:03 17:47:11-08:00
    Dict: File:FileAccessDate = 2022:03:27 08:28:16-07:00
    Dict: File:FileCreateDate = 2022:03:03 17:47:11-08:00
    Dict: File:FilePermissions = 100666
    Dict: File:FileType = JPEG
    Dict: File:FileTypeExtension = JPG
    Dict: File:MIMEType = image/jpeg
    Dict: File:ImageWidth = 70
    Dict: File:ImageHeight = 46
    Dict: File:EncodingProcess = 0
    Dict: File:BitsPerSample = 8
    Dict: File:ColorComponents = 3
    Dict: File:YCbCrSubSampling = 2 2
    Dict: JFIF:JFIFVersion = 1 1
    Dict: JFIF:ResolutionUnit = 1
    Dict: JFIF:XResolution = 72
    Dict: JFIF:YResolution = 72
    Dict: XMP:XMPToolkit = Image::ExifTool 8.85
    Dict: XMP:Subject = Röschen
    Dict: Composite:ImageSize = 70 46
    Dict: Composite:Megapixels = 0.00322
    
  • Get some tags in multiple files

    from exiftool import ExifToolHelper
    with ExifToolHelper() as et:
        for d in et.get_tags(["rose.jpg", "skyblue.png"], tags=["FileSize", "ImageSize"]):
            for k, v in d.items():
                print(f"Dict: {k} = {v}")
    
    Dict: SourceFile = rose.jpg
    Dict: File:FileSize = 4949
    Dict: Composite:ImageSize = 70 46
    Dict: SourceFile = skyblue.png
    Dict: File:FileSize = 206
    Dict: Composite:ImageSize = 64 64
    

Setting Tags

  • Setting date and time of some files to current time, overwriting file, but preserving original mod date

    from exiftool import ExifToolHelper
    from datetime import datetime
    with ExifToolHelper() as et:
        now = datetime.strftime(datetime.now(), "%Y:%m:%d %H:%M:%S")
        et.set_tags(
            ["rose.jpg", "skyblue.png"],
            tags={"DateTimeOriginal": now},
            params=["-P", "-overwrite_original"]
        )
    

    (No output is returned if successful)

  • Setting keywords for a file.

    from exiftool import ExifToolHelper
    with ExifToolHelper() as et:
        et.set_tags(
            ["rose.jpg", "skyblue.png"],
            tags={"Keywords": ["sunny", "nice day", "cool", "awesome"]}
        )
    

    (No output is returned if successful)

Exceptions

By default, ExifToolHelper has some built-in error checking, making the methods safer to use than calling the base methods directly.

Warning

While “safer”, the error checking isn’t fool-proof. There are a lot of cases where exiftool just silently ignores bad input and doesn’t indicate an error.

  • Example using get_tags() on a list which includes a non-existent file

    • ExifToolHelper with error-checking, using exiftool.ExifToolHelper.get_tags()

      from exiftool import ExifToolHelper
      with ExifToolHelper() as et:
          print(et.get_tags(
              ["rose.jpg", "skyblue.png", "non-existent file.tif"],
              tags=["FileSize"]
          ))
      

      Output:

      Traceback (most recent call last):
        File "T:\example.py", line 7, in <module>
          et.get_tags(["rose.jpg", "skyblue.png", "non-existent file.tif"], tags=["FileSize"])
        File "T:\pyexiftool\exiftool\helper.py", line 353, in get_tags
          ret = self.execute_json(*exec_params)
        File "T:\pyexiftool\exiftool\exiftool.py", line 1030, in execute_json
          result = self.execute("-j", *params)  # stdout
        File "T:\pyexiftool\exiftool\helper.py", line 119, in execute
          raise ExifToolExecuteError(self._last_status, self._last_stdout, self._last_stderr, params)
      exiftool.exceptions.ExifToolExecuteError: execute returned a non-zero exit status: 1
      
    • ExifTool only, without error checking, using exiftool.ExifTool.execute_json() (Note how the missing file is silently ignored and doesn’t show up in returned list.)

      from exiftool import ExifToolHelper
      with ExifToolHelper() as et:
          print(et.get_tags(
              ["rose.jpg", "skyblue.png", "non-existent file.tif"],
              tags=["FileSize"]
          ))
      

      Output:

      [{'SourceFile': 'rose.jpg', 'File:FileSize': 4949}, {'SourceFile': 'skyblue.png', 'File:FileSize': 206}]
      
  • Example using exiftool.ExifToolHelper.get_tags() with a typo. Let’s say you wanted to get_tags(), but accidentally copy/pasted something and left a = character behind (deletes tag rather than getting!)…

    • Using exiftool.ExifToolHelper.get_tags()

      from exiftool import ExifToolHelper
      with ExifToolHelper() as et:
          print(et.get_tags(["skyblue.png"], tags=["XMP:Subject=hi"]))
      

      Output:

      Traceback (most recent call last):
        File "T:\example.py", line 7, in <module>
          print(et.get_tags(["skyblue.png"], tags=["XMP:Subject=hi"]))
        File "T:\pyexiftool\exiftool\helper.py", line 341, in get_tags
          self.__class__._check_tag_list(final_tags)
        File "T:\pyexiftool\exiftool\helper.py", line 574, in _check_tag_list
          raise ExifToolTagNameError(t)
      exiftool.exceptions.ExifToolTagNameError: Invalid Tag Name found: "XMP:Subject=hi"
      
    • Using exiftool.ExifTool.execute_json(). It still raises an exception, but more cryptic and difficult to debug

      from exiftool import ExifTool
      with ExifTool() as et:
          print(et.execute_json(*["-XMP:Subject=hi"] + ["skyblue.png"]))
      

      Output:

      Traceback (most recent call last):
        File "T:\example.py", line 7, in <module>
          print(et.execute_json(*["-XMP:Subject=hi"] + ["skyblue.png"]))
        File "T:\pyexiftool\exiftool\exiftool.py", line 1052, in execute_json
          raise ExifToolOutputEmptyError(self._last_status, self._last_stdout, self._last_stderr, params)
      exiftool.exceptions.ExifToolOutputEmptyError: execute_json expected output on stdout but got none
      
    • Using exiftool.ExifTool.execute(). No errors, but you have now written to the file instead of reading from it!

      from exiftool import ExifTool
      with ExifTool() as et:
          print(et.execute(*["-XMP:Subject=hi"] + ["skyblue.png"]))
      

      Output:

      1 image files updated
      

ExifTool

Using methods provided by exiftool.ExifTool

Calling execute() or execute_json() provides raw functionality for advanced use cases. Use with care!