So, I’m into photography, and I like to keep an eye on the shutter count of my camera. It’s a vital metric: The higher it gets, the more likely it is to start causing problems.
My Nikon D850 is supposed to be good for 200,000 shots, but I’ve seen cameras that have way exceeded that and still work fine. However, I’m not planning on selling mine anytime soon, but I wanted a quick way to check the count using just a raw photo from the camera as a CLI (Command-Line Interface).
The Python package exifread
gives access to that number, even though some customization is still required because the EXIF (Exchangeable Image File Format) parameters for the shutter count aren’t always the same.
So, I’ve created a Python script to tackle this and turned it into a handy CLI tool. Head over to the post to grab the entire code, complete with plenty of comments to walk you through every step, or clone the git repository.
Overview
This is not a documentation. For a thorough documentation, please see the README.md
file inside the repository on GitLab or GitHub.
Installation
To use my Python Shutter Count CLI, you can clone the repository:
git clone https://gitlab.com/thaikolja/python-shutter-counter.git
If you only want the files without the Git commits baked in, you can also download it as a .zip file.
Usage
Use the CLI either as a local tool for your command line. The easiest way to do this is by creating a Bash alias
in your .zshrc
(macOS) or .bashrc
(Linux) file:
alias shuttercounter="python3 /absolute/path/to/main.py"
After that, you can simply run shuttercounter path/to/image.jpg
in your terminal to display the total shutter count of the camera with which the image was taken. Run shuttercounter --help
for the list of available arguments.
Code
from exifread import process_file
from logging import basicConfig, warning, ERROR, error
from sys import exit, version_info, argv
# Set the logging level to ERROR
basicConfig(level=ERROR)
class ShutterCounter:
"""
A class used to represent a Shutter Counter
Attributes
----------
image_path : str
a formatted string to print out the path where the image is located
shutter_tag : str
a string representing the shutter tag (default is 'MakerNote TotalShutterReleases')
supported_models : list
a list containing the supported camera models (default is ['NIKON D850', 'NIKON D810', 'NIKON D800'])
Methods
-------
get_shutter_count(output_type: int or str = 'int') -> int or str or None:
Returns the shutter count of the image if possible, else returns None
"""
def __init__(self, image_path, shutter_tag='MakerNote TotalShutterReleases'):
"""
Constructs all the necessary attributes for the ShutterCounter object.
Parameters
----------
image_path : str
the path where the image is located
shutter_tag : str
the shutter tag (default is 'MakerNote TotalShutterReleases')
"""
self.image_path = image_path
self.shutter_tag = shutter_tag
self.supported_models = [
'NIKON D850',
'NIKON D810',
'NIKON D800'
]
def get_shutter_count(self, output_type: int or str = 'int') -> int or str or None:
"""
Returns the shutter count of the image if possible, else returns None
Parameters
----------
output_type : int or str
the type of the output (default is 'int')
Returns
-------
int or str or None
the shutter count if possible, else None
"""
try:
with open(self.image_path, 'rb') as file:
tags = process_file(file)
camera_model = str(tags['Image Model'])
if camera_model not in self.supported_models:
error(f" Your camera model {camera_model} is currently not supported.")
exit(1)
if self.shutter_tag in tags:
shutter_count_str = str(tags[self.shutter_tag])
try:
output = str(f"Shutter count: {shutter_count_str}")
if len(argv) > 2 and argv[2] == 'int':
output = int(shutter_count_str)
return output
except ValueError:
error(f" Could not convert shutter count to ${output_type}: {shutter_count_str}")
exit(1)
else:
warning(f" The shutter count could not be found in the EXIF data.")
exit(1)
except (FileNotFoundError, IOError):
error(f" Could not find or open the image file: {self.image_path}")
exit(1)
# Main execution
if __name__ == "__main__":
result_type = 'int'
# Check if the image path is provided as an argument
if len(argv) < 2:
print('Please provide an image path as an argument.')
exit(1)
# Check if the result type is provided as an argument
if len(argv) > 2 and argv[2] == 'str':
result_type = argv[2]
# Check if help is requested
if argv[1] == '-h' or argv[1] == '--help':
print('Usage: python main.py <image_path> (int|str)')
exit(1)
# Check if the Python version is 3 or above
if version_info[0] < 3:
error(" This script requires Python 3.")
exit(1)
# Create a ShutterCounter object
counter = ShutterCounter(argv[1])
# Get the shutter count
shutter_count = counter.get_shutter_count()
# Print the shutter count
print(shutter_count)
Feel free to collaborate or create pull requests by creating a fork if you think you can improve this little tool!