FIX: Python exception handling across different versions
[freefoam.git] / bin / freefoam-job.py.in
blob58ce17e49185f01a060fe838a45fd74bbb20dbaf
1 #!@PYTHON_EXECUTABLE@
2 #-------------------------------------------------------------------------------
3 # ______ _ ____ __ __
4 # | ____| _| |_ / __ \ /\ | \/ |
5 # | |__ _ __ ___ ___ / \| | | | / \ | \ / |
6 # | __| '__/ _ \/ _ ( (| |) ) | | |/ /\ \ | |\/| |
7 # | | | | | __/ __/\_ _/| |__| / ____ \| | | |
8 # |_| |_| \___|\___| |_| \____/_/ \_\_| |_|
10 # FreeFOAM: The Cross-Platform CFD Toolkit
12 # Copyright (C) 2008-2012 Michael Wild <themiwi@users.sf.net>
13 # Gerber van der Graaf <gerber_graaf@users.sf.net>
14 #-------------------------------------------------------------------------------
15 # License
16 # This file is part of FreeFOAM.
18 # FreeFOAM is free software: you can redistribute it and/or modify it
19 # under the terms of the GNU General Public License as published by the
20 # Free Software Foundation, either version 3 of the License, or (at your
21 # option) any later version.
23 # FreeFOAM is distributed in the hope that it will be useful, but WITHOUT
24 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 # for more details.
28 # You should have received a copy of the GNU General Public License
29 # along with FreeFOAM. If not, see <http://www.gnu.org/licenses/>.
31 # Script
32 # freefoam-job
34 # Description
35 # Run a freefoam job in background and redirect the output to a log-file.
37 #------------------------------------------------------------------------------
39 """Usage: freefoam@PY_SCRIPT_SUFFIX@ job [-s] [-p] [-log <logfile>] [-fg]
40 [-h, -help] <application> [OPTIONS]
42 Run a freefoam job in background and redirect the output to a log-file.
44 Options
45 -------
46 -s Also send output to the terminal
47 -p Parallel run of processors
48 -log <logfile> Specify logfile name for output, defaults to 'log'
49 -fg Run the job in the foreground (i.e. don't background it)
50 -h, -help Display this help message
51 <application> The FreeFOAM application to run
52 [OPTIONS] Arguments and options to be passed to the application
54 """
56 import FreeFOAM.util
57 import FreeFOAM.run
58 import os
59 import sys
60 import subprocess
61 # want to be future proof
62 sys.path.insert(0, '@FOAM_PYTHON_DIR@')
63 from FreeFOAM.compat import *
65 # parse options
66 screen = False
67 parallel = False
68 logName = 'log'
69 foreground = False
70 application = None
71 args = sys.argv[1:]
72 while len(args) > 0:
73 a = args[0]
74 if a == '-s':
75 screen = True
76 del args[0]
77 elif a == '-p':
78 parallel = True
79 del args[0]
80 elif a == '-log':
81 if len(args) < 2:
82 sys.stderr.write('Error: The -log option requires an argument\n')
83 sys.exit(1)
84 logName = args[1]
85 del args[0:2]
86 elif a == '-fg':
87 foreground = True
88 del args[0]
89 elif a == '-h' or a == '-help':
90 print(__doc__)
91 sys.exit(0)
92 elif a[0] == '-':
93 sys.stderr.write('Error: unknown option "%s"\n'%a)
94 sys.stderr.write(__doc__+'\n')
95 sys.exit(1)
96 else:
97 application = a
98 del args[0]
99 break
101 if not application:
102 sys.stderr.write("Error: No application specified")
103 sys.stderr.write(__doc__+'\n')
104 sys.exit(1)
106 # now look for the -case option in the remaining arguments
107 case = '.'
108 for i, a in enumerate(args):
109 if a == '-case':
110 case = args[i+1]
111 del args[i:i+2]
112 break
114 # if we are to run in the background, fork (MUST BE FIRST!)
115 if not foreground:
116 pid = os.fork()
117 if pid:
118 # this is the parent process
119 sys.exit(0)
121 # this is the child process continuing here (if we forked)
123 # create the log file
124 if screen:
125 logFile = FreeFOAM.util.Tee(logName, 'wt')
126 else:
127 logFile = open(logName, 'wt')
129 # create the runner instance
130 if parallel:
131 runner = FreeFOAM.run.ParallelRunner()
132 else:
133 runner = FreeFOAM.run.Runner()
135 # run the thing (needs a bit of hackery...)
136 runner.run(application, case=case, parallel=parallel, args=args,
137 stdout=subprocess.PIPE, stderr=subprocess.STDOUT, background=True)
139 # retrieve the output and write it to the log file as long as the thing runs
140 while True:
141 lines = runner.getProcess().stdout.readlines()
142 if len(lines) and not isinstance(lines[0], str):
143 lines = list(map(lambda l: l.decode(), lines))
144 logFile.writelines(lines)
145 returncode = runner.poll()
146 if returncode != None:
147 break
149 sys.exit(returncode)
151 # ------------------- vim: set sw=3 sts=3 ft=python et: ------------ end-of-file