diff --git a/CHANGELOG.md b/CHANGELOG.md index 61fadb98a6..5620ae25e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Versioned according to [Semantic Versioning](http://semver.org/). Changed: * workspace bagger will create files with extension + * `save_mets` is atomic now, #278, #285 ## [1.0.0b15] - 2019-08-14 diff --git a/ocrd/ocrd/workspace.py b/ocrd/ocrd/workspace.py index 0cca59d8a9..da818fc53d 100644 --- a/ocrd/ocrd/workspace.py +++ b/ocrd/ocrd/workspace.py @@ -5,6 +5,7 @@ import cv2 from PIL import Image import numpy as np +from atomicwrites import atomic_write from ocrd_models import OcrdMets, OcrdExif from ocrd_utils import getLogger, is_local_filename, abspath, pushd_popd @@ -170,8 +171,8 @@ def save_mets(self): log.info("Saving mets '%s'" % self.mets_target) if self.automatic_backup: WorkspaceBackupManager(self).add() - with open(self.mets_target, 'wb') as f: - f.write(self.mets.to_xml(xmllint=True)) + with atomic_write(self.mets_target, overwrite=True) as f: + f.write(self.mets.to_xml(xmllint=True).decode('utf-8')) def resolve_image_exif(self, image_url): """ diff --git a/ocrd/ocrd/workspace_backup.py b/ocrd/ocrd/workspace_backup.py index a83e198765..57030abc94 100644 --- a/ocrd/ocrd/workspace_backup.py +++ b/ocrd/ocrd/workspace_backup.py @@ -10,6 +10,8 @@ from .constants import BACKUP_DIR +from atomicwrites import atomic_write + def _chksum(s): return hashlib.sha256(s).hexdigest() @@ -83,8 +85,8 @@ def add(self): mets_file = join(d, 'mets.xml') log.info("Backing up to %s" % mets_file) makedirs(d) - with open(mets_file, 'wb') as f: - f.write(mets_str) + with atomic_write(mets_file, overwrite=True) as f: + f.write(mets_str.decode('utf-8')) return chksum def list(self): diff --git a/ocrd/requirements.txt b/ocrd/requirements.txt index 31601f2e1f..6a2f8eb132 100644 --- a/ocrd/requirements.txt +++ b/ocrd/requirements.txt @@ -9,3 +9,4 @@ opencv-python-headless Flask jsonschema pyyaml +atomicwrites >= 1.3.0