The Gaudi Framework  v32r0 (3325bb39)
Main.py
Go to the documentation of this file.
1 import sys
2 import os
3 from time import time
4 from Gaudi import Configuration
5 import logging
6 
7 log = logging.getLogger(__name__)
8 
9 
10 def toOpt(value):
11  '''
12  Helper to convert values to old .opts format.
13 
14  >>> print toOpt('some "text"')
15  "some \\"text\\""
16  >>> print toOpt('first\\nsecond')
17  "first
18  second"
19  >>> print toOpt({'a': [1, 2, '3']})
20  {"a": [1, 2, "3"]}
21  '''
22  if isinstance(value, basestring):
23  return '"{0}"'.format(value.replace('"', '\\"'))
24  elif isinstance(value, dict):
25  return '{{{0}}}'.format(', '.join(
26  '{0}: {1}'.format(toOpt(k), toOpt(v))
27  for k, v in value.iteritems()))
28  elif hasattr(value, '__iter__'):
29  return '[{0}]'.format(', '.join(map(toOpt, value)))
30  else:
31  return repr(value)
32 
33 
34 class gaudimain(object):
35  def __init__(self):
36  from Configurables import ApplicationMgr
37  appMgr = ApplicationMgr()
38  if "GAUDIAPPNAME" in os.environ:
39  appMgr.AppName = str(os.environ["GAUDIAPPNAME"])
40  if "GAUDIAPPVERSION" in os.environ:
41  appMgr.AppVersion = str(os.environ["GAUDIAPPVERSION"])
42  self.log = logging.getLogger(__name__)
43  self.printsequence = False
44  self.application = 'Gaudi::Application'
45 
47  # ---------------------------------------------------
48  # set up Logging
49  # ----------------
50  # from multiprocessing import enableLogging, getLogger
51  import multiprocessing
52  # preliminaries for handlers/output files, etc.
53  from time import ctime
54  datetime = ctime()
55  datetime = datetime.replace(' ', '_')
56  outfile = open('gaudirun-%s.log' % (datetime), 'w')
57  # two handlers, one for a log file, one for terminal
58  streamhandler = logging.StreamHandler(stream=outfile)
59  console = logging.StreamHandler()
60  # create formatter : the params in parentheses are variable names available via logging
61  formatter = logging.Formatter(
62  "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
63  # add formatter to Handler
64  streamhandler.setFormatter(formatter)
65  console.setFormatter(formatter)
66  # now, configure the logger
67  # enableLogging( level=0 )
68  # self.log = getLogger()
69  self.log = multiprocessing.log_to_stderr()
70  self.log.setLevel(logging.INFO)
71  self.log.name = 'Gaudi/Main.py Logger'
72  self.log.handlers = []
73  # add handlers to logger : one for output to a file, one for console output
74  self.log.addHandler(streamhandler)
75  self.log.addHandler(console)
76  self.log.removeHandler(console)
77  # set level!!
78  self.log.setLevel = logging.INFO
79  # ---------------------------------------------------
80 
81  def generatePyOutput(self, all=False):
82  from pprint import pformat
83  conf_dict = Configuration.configurationDict(all)
84  return pformat(conf_dict)
85 
86  def generateOptsOutput(self, all=False):
87  from pprint import pformat
88  conf_dict = Configuration.configurationDict(all)
89  out = []
90  names = conf_dict.keys()
91  names.sort()
92  for n in names:
93  props = conf_dict[n].keys()
94  props.sort()
95  for p in props:
96  out.append('%s.%s = %s;' % (n, p, toOpt(conf_dict[n][p])))
97  return "\n".join(out)
98 
99  def _writepickle(self, filename):
100  # --- Lets take the first file input file as the name of the pickle file
101  import pickle
102  output = open(filename, 'wb')
103  # Dump only the the configurables that make sense to dump (not User ones)
104  from GaudiKernel.Proxy.Configurable import getNeededConfigurables
105  to_dump = {}
106  for n in getNeededConfigurables():
107  to_dump[n] = Configuration.allConfigurables[n]
108  pickle.dump(to_dump, output, -1)
109  output.close()
110 
111  def printconfig(self, old_format=False, all=False):
112  msg = 'Dumping all configurables and properties'
113  if not all:
114  msg += ' (different from default)'
115  log.info(msg)
116  conf_dict = Configuration.configurationDict(all)
117  if old_format:
118  print self.generateOptsOutput(all)
119  else:
120  print self.generatePyOutput(all)
121 
122  def writeconfig(self, filename, all=False):
123  write = {".pkl": lambda filename, all: self._writepickle(filename),
124  ".py": lambda filename, all: open(filename, "w").write(self.generatePyOutput(all) + "\n"),
125  ".opts": lambda filename, all: open(filename, "w").write(self.generateOptsOutput(all) + "\n"),
126  }
127  from os.path import splitext
128  ext = splitext(filename)[1]
129  if ext in write:
130  write[ext](filename, all)
131  else:
132  log.error("Unknown file type '%s'. Must be any of %r.", ext,
133  write.keys())
134  sys.exit(1)
135 
136  # Instantiate and run the application.
137  # Depending on the number of CPUs (ncpus) specified, it start
138  def run(self, attach_debugger, ncpus=None):
139  if not ncpus:
140  if os.environ.get('GAUDIRUN_USE_OLDINIT'):
141  result = self.runSerialOld(attach_debugger)
142  else:
143  # Standard sequential mode
144  result = self.runSerial(attach_debugger)
145  else:
146  # Otherwise, run with the specified number of cpus
147  result = self.runParallel(ncpus)
148  return result
149 
150  def hookDebugger(self, debugger='gdb'):
151  import os
152  self.log.info('attaching debugger to PID ' + str(os.getpid()))
153  pid = os.spawnvp(os.P_NOWAIT, debugger,
154  [debugger, '-q', 'python',
155  str(os.getpid())])
156 
157  # give debugger some time to attach to the python process
158  import time
159  time.sleep(5)
160 
161  # verify the process' existence (will raise OSError if failed)
162  os.waitpid(pid, os.WNOHANG)
163  os.kill(pid, 0)
164  return
165 
166  def runSerial(self, attach_debugger):
167  try:
168  from GaudiKernel.Proxy.Configurable import expandvars
169  except ImportError:
170  # pass-through implementation if expandvars is not defined (AthenaCommon)
171  def expandvars(data):
172  return data
173 
174  from GaudiKernel.Proxy.Configurable import Configurable, getNeededConfigurables
175 
176  self.log.debug('runSerial: apply options')
177  conf_dict = {'ApplicationMgr.JobOptionsType': '"NONE"'}
178 
179  # FIXME: this is to make sure special properties are correctly
180  # expanded before we fill conf_dict
181  for c in Configurable.allConfigurables.values():
182  if hasattr(c, 'getValuedProperties'):
183  c.getValuedProperties()
184 
185  for n in getNeededConfigurables():
186  c = Configurable.allConfigurables[n]
187  for p, v in c.getValuedProperties().items():
188  v = expandvars(v)
189  # Note: AthenaCommon.Configurable does not have Configurable.PropertyReference
190  if hasattr(Configurable, "PropertyReference") and type(
191  v) == Configurable.PropertyReference:
192  # this is done in "getFullName", but the exception is ignored,
193  # so we do it again to get it
194  v = v.__resolve__()
195  if type(v) == str:
196  v = '"%s"' % v # need double quotes
197  elif type(v) == long:
198  v = '%d' % v # prevent pending 'L'
199  conf_dict['{}.{}'.format(n, p)] = str(v)
200 
201  if self.printsequence:
202  conf_dict['ApplicationMgr.PrintAlgsSequence'] = 'true'
203 
204  if hasattr(Configurable, "_configurationLocked"):
205  Configurable._configurationLocked = True
206 
207  if attach_debugger:
208  self.hookDebugger()
209 
210  self.log.debug('-' * 80)
211  self.log.debug('%s: running in serial mode', __name__)
212  self.log.debug('-' * 80)
213  sysStart = time()
214 
215  import Gaudi
216  app = Gaudi.Application.create(self.application, conf_dict)
217  retcode = app.run()
218 
219  sysTime = time() - sysStart
220  self.log.debug('-' * 80)
221  self.log.debug('%s: serial system finished, time taken: %5.4fs',
222  __name__, sysTime)
223  self.log.debug('-' * 80)
224 
225  return retcode
226 
227  def runParallel(self, ncpus):
228  self.setupParallelLogging()
229  from Gaudi.Configuration import Configurable
230  import GaudiMP.GMPBase as gpp
231  c = Configurable.allConfigurables
232  self.log.info('-' * 80)
233  self.log.info('%s: Parallel Mode : %i ', __name__, ncpus)
234  for name, value in [
235  ('platrofm', ' '.join(os.uname())),
236  ('config', os.environ.get('BINARY_TAG')
237  or os.environ.get('CMTCONFIG')),
238  ('app. name', os.environ.get('GAUDIAPPNAME')),
239  ('app. version', os.environ.get('GAUDIAPPVERSION')),
240  ]:
241  self.log.info('%s: %30s : %s ', __name__, name, value
242  or 'Undefined')
243  try:
244  events = str(c['ApplicationMgr'].EvtMax)
245  except:
246  events = "Undetermined"
247  self.log.info('%s: Events Specified : %s ', __name__, events)
248  self.log.info('-' * 80)
249  # Parall = gpp.Coordinator(ncpus, shared, c, self.log)
250  Parall = gpp.Coord(ncpus, c, self.log)
251  sysStart = time()
252  sc = Parall.Go()
253  self.log.info('MAIN.PY : received %s from Coordinator' % (sc))
254  if sc.isFailure():
255  return 1
256  sysTime = time() - sysStart
257  self.log.name = 'Gaudi/Main.py Logger'
258  self.log.info('-' * 80)
259  self.log.info('%s: parallel system finished, time taken: %5.4fs',
260  __name__, sysTime)
261  self.log.info('-' * 80)
262  return 0
def run(self, attach_debugger, ncpus=None)
Definition: Main.py:138
def setupParallelLogging(self)
Definition: Main.py:46
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:109
def toOpt(value)
Definition: Main.py:10
def _writepickle(self, filename)
Definition: Main.py:99
def generateOptsOutput(self, all=False)
Definition: Main.py:86
getNeededConfigurables
Definition: Proxy.py:21
def runParallel(self, ncpus)
Definition: Main.py:227
def hookDebugger(self, debugger='gdb')
Definition: Main.py:150
def generatePyOutput(self, all=False)
Definition: Main.py:81
struct GAUDI_API map
Parametrisation class for map-like implementation.
def create(cls, appType, opts)
Definition: __init__.py:83
The Application Manager class.
def __init__(self)
Definition: Main.py:35
def printconfig(self, old_format=False, all=False)
Definition: Main.py:111
def writeconfig(self, filename, all=False)
Definition: Main.py:122
def runSerial(self, attach_debugger)
Definition: Main.py:166