Cleanup exiftool processes when exiting, #449

This commit is contained in:
Rhet Turnbull
2021-05-19 06:16:52 -07:00
parent df167c00eb
commit 9f2268fb2b
3 changed files with 26 additions and 5 deletions

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.42.21" __version__ = "0.42.22"

View File

@@ -6,19 +6,28 @@
If these aren't important to you, I highly recommend you use Sven Marnach's excellent If these aren't important to you, I highly recommend you use Sven Marnach's excellent
pyexiftool: https://github.com/smarnach/pyexiftool which provides more functionality """ pyexiftool: https://github.com/smarnach/pyexiftool which provides more functionality """
import atexit
import json import json
import logging import logging
import os import os
import re import re
import shutil import shutil
import subprocess import subprocess
from functools import lru_cache # pylint: disable=syntax-error
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from functools import lru_cache # pylint: disable=syntax-error
# exiftool -stay_open commands outputs this EOF marker after command is run # exiftool -stay_open commands outputs this EOF marker after command is run
EXIFTOOL_STAYOPEN_EOF = "{ready}" EXIFTOOL_STAYOPEN_EOF = "{ready}"
EXIFTOOL_STAYOPEN_EOF_LEN = len(EXIFTOOL_STAYOPEN_EOF) EXIFTOOL_STAYOPEN_EOF_LEN = len(EXIFTOOL_STAYOPEN_EOF)
# list of exiftool processes to cleanup when exiting or when terminate is called
EXIFTOOL_PROCESSES = []
@atexit.register
def terminate_exiftool():
"""Terminate any running ExifTool subprocesses; call this to cleanup when done using ExifTool """
for proc in EXIFTOOL_PROCESSES:
proc._stop_proc()
@lru_cache(maxsize=1) @lru_cache(maxsize=1)
def get_exiftool_path(): def get_exiftool_path():
@@ -61,6 +70,8 @@ class _ExifToolProc:
self._exiftool = exiftool or get_exiftool_path() self._exiftool = exiftool or get_exiftool_path()
self._start_proc() self._start_proc()
EXIFTOOL_PROCESSES.append(self)
@property @property
def process(self): def process(self):
""" return the exiftool subprocess """ """ return the exiftool subprocess """
@@ -117,9 +128,6 @@ class _ExifToolProc:
try: try:
self._process.communicate(timeout=5) self._process.communicate(timeout=5)
except subprocess.TimeoutExpired: except subprocess.TimeoutExpired:
logging.warning(
f"exiftool pid {self._process.pid} did not exit, killing it"
)
self._process.kill() self._process.kill()
self._process.communicate() self._process.communicate()

View File

@@ -417,3 +417,16 @@ def test_photoinfo_exiftool_none():
photo = photosdb.photos(uuid=[uuid])[0] photo = photosdb.photos(uuid=[uuid])[0]
exiftool = photo.exiftool exiftool = photo.exiftool
assert exiftool is None assert exiftool is None
def test_exiftool_terminate():
""" Test that exiftool process is terminated when exiftool.terminate() is called """
import osxphotos.exiftool
import subprocess
exif1 = osxphotos.exiftool.ExifTool(TEST_FILE_ONE_KEYWORD)
osxphotos.exiftool.terminate_exiftool()
ps = subprocess.run(["ps"], capture_output=True)
stdout = ps.stdout.decode("utf-8")
assert "exiftool -stay_open" not in stdout