Source code for cis_interface.drivers.ModelDriver

#
# This should not be used directly by modelers
#
import os
import subprocess
import sys
from pprint import pformat
from cis_interface.drivers.Driver import Driver
from cis_interface import backwards


[docs]def preexec(): # pragma: no cover # Don't forward signals - used to ignore signals os.setpgrp()
[docs]class ModelDriver(Driver): r"""Base class form Model drivers. Args: name (str): Driver name. args (str or list): Argument(s) for running the model on the command line. \*\*kwargs: Additional keyword arguments are passed to parent class's __init__ method. Attributes (in additon to parent class's): args (list): Argument(s) for running the model on the command line. process (:class:`subprocess.Popen`): Process used to run the model. env (dict): Dictionary of environment variables. """ def __init__(self, name, args, **kwargs): super(ModelDriver, self).__init__(name, **kwargs) self.debug(str(args)) if isinstance(args, str): self.args = [args] else: self.args = args self.process = None # This gets added to before run with the channel args self.env = os.environ.copy()
[docs] def run(self): r"""Run the model on a new process, receiving output from.""" self.debug(':run %s from %s with cwd %s and env %s', self.args, os.getcwd(), self.workingDir, pformat(self.env)) with self.lock: try: self.process = subprocess.Popen( ['stdbuf', '-o0'] + self.args, bufsize=0, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, env=self.env, cwd=self.workingDir, preexec_fn=preexec) except: # pragma: debug self.exception('(%s): Exception starting in %s with wd %s', self.args, os.getcwd, self.workingDir) return # Re-direct output while True: with self.lock: if self.process: line = self.process.stdout.readline() else: return if not line: break sys.stdout.write(backwards.bytes2unicode(line)) sys.stdout.flush() self.debug(':run: done')
[docs] def terminate(self): r"""Terminate the process running the model.""" self.debug(':terminate()') with self.lock: if self.process: self.debug(':terminate(): terminate process') self.process.terminate() self.process = None