Cleanup exiftool processes when exiting, #449
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.42.21"
|
__version__ = "0.42.22"
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user