@@ -287,7 +287,7 @@ def setTempDirectory(self, customBuildDirectory):
287287 def getWorkDirectory (self ):
288288 return self .tempdir
289289
290- def _run_cmd (self , cmd : list ):
290+ def _run_cmd (self , cmd : list , timeout : Optional [ int ] = None ):
291291 logger .debug ("Run OM command %s in %s" , cmd , self .tempdir )
292292
293293 if platform .system () == "Windows" :
@@ -310,19 +310,18 @@ def _run_cmd(self, cmd: list):
310310 my_env = None
311311
312312 try :
313- p = subprocess .Popen (cmd , env = my_env , stdout = subprocess . PIPE ,
314- stderr = subprocess . PIPE , cwd = self . tempdir )
315- stdout , stderr = p . communicate ()
316-
317- stdout = stdout . decode ( 'ascii' ). strip ()
318- stderr = stderr . decode ( 'ascii' ). strip ( )
313+ cmdres = subprocess .run (cmd , capture_output = True , text = True , env = my_env , cwd = self . tempdir ,
314+ timeout = timeout )
315+ stdout = cmdres . stdout . strip ()
316+ stderr = cmdres . stderr . strip ()
317+ if cmdres . returncode != 0 :
318+ raise ModelicaSystemError ( f"Error running command { cmd } : return code = { cmdres . returncode } " )
319319 if stderr :
320320 raise ModelicaSystemError (f"Error running command { cmd } : { stderr } " )
321321 if self ._verbose and stdout :
322322 logger .info ("OM output for command %s:\n %s" , cmd , stdout )
323- # check process returncode, some errors don't print to stderr
324- if p .wait ():
325- raise ModelicaSystemError (f"Error running command { cmd } : nonzero returncode" )
323+ except subprocess .TimeoutExpired :
324+ raise ModelicaSystemError (f"Timeout running command { repr (cmd )} " )
326325 except Exception as e :
327326 raise ModelicaSystemError (f"Exception { type (e )} running command { cmd } : { e } " )
328327
@@ -675,7 +674,7 @@ def get_exe_file(self) -> pathlib.Path:
675674 else :
676675 return pathlib .Path (self .tempdir ) / self .modelName
677676
678- def simulate (self , resultfile = None , simflags = None ): # 11
677+ def simulate (self , resultfile = None , simflags = None , timeout : Optional [ int ] = None ): # 11
679678 """
680679 This method simulates model according to the simulation options.
681680 usage
@@ -738,7 +737,7 @@ def simulate(self, resultfile=None, simflags=None): # 11
738737
739738 cmd = exe_file .as_posix () + override + csvinput + r + simflags
740739 cmd = [s for s in cmd .split (' ' ) if s ]
741- self ._run_cmd (cmd = cmd )
740+ self ._run_cmd (cmd = cmd , timeout = timeout )
742741 self .simulationFlag = True
743742
744743 # to extract simulation results
@@ -1055,13 +1054,15 @@ def optimize(self): # 21
10551054
10561055 return optimizeResult
10571056
1058- def linearize (self , lintime : Optional [float ] = None , simflags : Optional [str ] = None ) -> LinearizationResult :
1057+ def linearize (self , lintime : Optional [float ] = None , simflags : Optional [str ] = None ,
1058+ timeout : Optional [int ] = None ) -> LinearizationResult :
10591059 """Linearize the model according to linearOptions.
10601060
10611061 Args:
10621062 lintime: Override linearOptions["stopTime"] value.
10631063 simflags: A string of extra command line flags for the model
10641064 binary.
1065+ timeout: Possible timeout for the execution of OM.
10651066
10661067 Returns:
10671068 A LinearizationResult object is returned. This allows several
@@ -1116,7 +1117,7 @@ def linearize(self, lintime: Optional[float] = None, simflags: Optional[str] = N
11161117 else :
11171118 cmd = exe_file .as_posix () + linruntime + override + csvinput + simflags
11181119 cmd = [s for s in cmd .split (' ' ) if s ]
1119- self ._run_cmd (cmd = cmd )
1120+ self ._run_cmd (cmd = cmd , timeout = timeout )
11201121
11211122 # code to get the matrix and linear inputs, outputs and states
11221123 linearFile = pathlib .Path (self .tempdir ) / "linearized_model.py"
0 commit comments