From 4adafc8417d1aa75345e5e52b3ae594c3b099bec Mon Sep 17 00:00:00 2001 From: David Hammer <dhammer@mailbox.org> Date: Thu, 31 Aug 2023 14:58:27 +0200 Subject: [PATCH] Improve temporary file handling --- src/calng/CrystfelRunner.py | 40 ++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/calng/CrystfelRunner.py b/src/calng/CrystfelRunner.py index 48401f7d..086db51c 100644 --- a/src/calng/CrystfelRunner.py +++ b/src/calng/CrystfelRunner.py @@ -1,7 +1,9 @@ import itertools +import os import queue import re import subprocess +import tempfile import threading import time @@ -386,6 +388,12 @@ class CrystfelRunner(PythonDevice): self.startCrystfel() def startCrystfel(self): + if hasattr(self, "_temporary_stream_fd"): + # if we made up a temporary file already and stopped CrystFEL + if self.get("crystfelArgs.streamOutputPath") == self._temporary_stream_fd.name: + # then forget about it so we can make a new one + self.set("crystfelArgs.streamOutputPath", "") + delattr(self, "_temporary_stream_fd") self._run_crystfel() self.updateState(State.STARTED) @@ -407,7 +415,6 @@ class CrystfelRunner(PythonDevice): fashion). The argument should be a hash (via WebProxy, a JSON-encoded dict) with a list of strings (with newline characters already there) under 'fileContents'.""" - import tempfile fd = tempfile.NamedTemporaryFile(mode="w") fd.writelines(data["fileContents"]) fd.flush() @@ -516,7 +523,6 @@ class CrystfelRunner(PythonDevice): threading.Thread(target=server, daemon=True).start() def _run_crystfel(self): - import os env = os.environ.copy() env["PATH"] = ( self.get("crystfelArgs.crystfelBinPath") + @@ -524,21 +530,18 @@ class CrystfelRunner(PythonDevice): ) # we must have a stream output! # if empty, set it to something and delete after we are done reading it - streamOutputPath = self.get("crystfelArgs.streamOutputPath") - deleteOutput = False - if len(streamOutputPath) == 0: - # TODO: Is /tmp ok? - # the goal is only to prevent - name = self.get("deviceId").replace("/", "_") - streamOutputPath = f"/tmp/out_{name}.stream" - deleteOutput = True + if not self.get("crystfelArgs.streamOutputPath"): + stream_fd = tempfile.NamedTemporaryFile() + self._temporary_stream_fd = stream_fd + self.set("crystfelArgs.streamOutputPath", stream_fd.name) + stream_fn = self.get("crystfelArgs.streamOutputPath") args = [ "indexamajig", f"--zmq-input=tcp://localhost:{self.get('crystfelArgs.zmqPort')}", "--zmq-request=next", "--data-format=msgpack", "-o", - streamOutputPath, + stream_fn, "-g", self.get("crystfelArgs.geometryPath"), ] @@ -552,8 +555,7 @@ class CrystfelRunner(PythonDevice): # Somehow Karabo substitutes ["--int-radius=3,4,5"] with ["--int-radius=3", "4", "5"] for Danilo # and it adds \\ escape sequences for David H. # both of those "effects" are handled in the hack function below - fixed_misc = reparse_fix_comma_mess(self.get("crystfelArgs.misc")) - args += fixed_misc + args.extend(reparse_fix_comma_mess(self.get("crystfelArgs.misc"))) # this should override the --peaks option set by the user, if they # want to use an external peakfinder @@ -586,7 +588,7 @@ class CrystfelRunner(PythonDevice): ## do something with stream file #self._tail_proc = subprocess.Popen( - # ["tail", "-F", "-n", "+0", streamOutputPath], + # ["tail", "-F", "-n", "+0", stream_fn], # stdout=subprocess.PIPE, # stderr=subprocess.PIPE, # shell=False, @@ -619,7 +621,7 @@ class CrystfelRunner(PythonDevice): n_reflections = list() cell = list() det_centre = list() - with open(streamOutputPath, "r") as outFile: + with open(stream_fn, "r") as outFile: #for line in self._tail_proc.stdout: for line in outFile: if reading_chunk: @@ -669,14 +671,6 @@ class CrystfelRunner(PythonDevice): f"crystfelStats", Hash(*itertools.chain.from_iterable(results.items())) ) - # ... and delete output stream file if requested: - if deleteOutput: - try: - os.remove(streamOutputPath) - except: - pass - threading.Thread(target=collect_details, daemon=True).start() utils.add_unsafe_get(CrystfelRunner) - -- GitLab