HWRF  trunk@4391
util.py
1 #!/usr/bin/env python
2 
3 ##@namespace pom.util
4 #Utility scripts for the pom package.
5 #
6 #Many of the functions here are for just testing the python based
7 #MPIPOM scripts during its development, can be replaced with much
8 #sophisticated functions in the produtil modules.
9 #
10 #@note Please report bugs/questions/comments to bijuthomas(at)mail(dot)uri(dot)edu.
11 #@author Biju Thomas, GSO, University of Rhode Island.
12 #@date June 8, 2014
13 
14 ##@var __all__
15 # List of symbols to provide by "from pom.util import *"
16 __all__ = 'ysplitter', 'trailzero',
17 
18 import os
19 import re
20 import sys
21 import shutil
22 import os.path
23 import datetime
24 import subprocess
25 
26 def ysplitter(ymdh):
27  """!Splits a string with a ten digit YYYYMMDDHH into components
28 
29  @param ymdh A string "YYYYMMDDHH" containing a date and hour.
30  @returns a tuple (y4,mm,mm1str,dd,hh) where y4 is the year, mm is
31  the month, dd is the day of the month and hh is the hour. The mmn1 is
32  the nearest month start/end boundary considering the day of month"""
33  y4=ymdh[0:4]
34  mm=ymdh[4:6]
35  dd=ymdh[6:8]
36  hh=ymdh[8:10]
37  if int(dd) <= 15:
38  mmn1 = int(mm) - 1
39  else:
40  mmn1 = int(mm) + 1
41  if mmn1 <= 9:
42  mm1str="0"+str(mmn1)
43  else:
44  mm1str=str(mmn1)
45  return (y4,mm, mm1str,dd,hh)
46 def trailzero(astr, n):
47  """!Returns a string of length n or greater, that consists of
48  n-len(astr) zeros followed by astr
49  @param n,astr the strings to consider"""
50  ( '0'*max(0,int(n)-len(astr)) ) + astr
51 def inpfile(filename,lst,logger=None):
52  """!Creates an input file from a list of strings
53  @param filename the input file to create
54  @param lst the list of strings
55  @param logger a logging.Logger for log messages"""
56  if logger is not None:
57  logger.info('%s: creating input file'%(filename,))
58  with open(filename,"w") as fid:
59  for mem in lst:
60  fid.write(mem)
61  fid.write("\n")
62 def remove(file):
63  """!Deletes the specified file. Ignores errors.
64  @param file The file to remove."""
65  if arg is None or arg=='':
66  return
67  if os.path.exists(arg):
68  try:
69  os.unlink(arg)
70  except EnvironmentError:
71  pass
72 def rmall(*args):
73  """!Deletes a list of files.
74  @param args All positional arguments contain names of files to remove."""
75  for arg in args:
76  remove(arg)
77 def copy(src, dest, force=True):
78  """!Copies the source to the destination without retaining permissions our group IDs.
79  Errors are ignored.
80 
81  @param src,dest Source and destination filenames.
82  @param force If True, the destination file is replaced if it already exists."""
83  try:
84  if os.path.exists(dest) and force:
85  os.remove(dest)
86  except os.error:
87  pass
88  try:
89  if os.path.exists(dest) and os.stat(dest).st_size==0:
90  os.remove(dest)
91  except os.error:
92  pass
93  try:
94  if not os.path.exists(dest):
95  if os.path.exists(src):
96  shutil.copy(src, dest)
97  else:
98  print("%s does NOT exists NOT copied" %(src))
99  else:
100  print("%s does exists NOT copied" %(dest))
101  except os.error:
102  pass
103 
104 def move(src, dest, force=True):
105  """!Renames the source file to the destination
106  @param src,dest The source and destination filenames.
107  @param force if True, the destination is replaced if it already exists."""
108  try:
109  if os.path.exists(dest) and force:
110  os.remove(dest)
111  except os.error:
112  pass
113  try:
114  if os.path.exists(dest) and os.stat(dest).st_size==0:
115  os.remove(dest)
116  except os.error:
117  pass
118  try:
119  if not os.path.exists(dest):
120  if os.path.exists(src):
121  shutil.move(src, dest)
122  else:
123  print("%s does NOT exists NOT moved" %(src))
124  else:
125  print("%s does exists NOT moved" %(dest))
126  except os.error:
127  pass
128 def link(src, dest):
129  """!Links the source file to the destination.
130  @param src,dest The source and destination filenames."""
131  try:
132  if os.path.exists(dest):
133  os.remove(dest)
134  except os.error:
135  pass
136  try:
137  if os.path.exists(src):
138  os.symlink(src, dest)
139  else:
140  print("%s does NOT exists NOT linked" %(src))
141  except os.error:
142  pass
143 
144 def runexe(nproc, rundir, exefile, stdin, stdout):
145  """!Runs an executable. Will only run on the NOAA Jet cluster.
146 
147  @warning Do not use this function. It only runs on NOAA Jet. It
148  lacks error checking other than returning the exit code and
149  there is no logging. Use the produtil.run module instead.
150  @param nproc Number of processors to use
151  @param rundir Directory in which to run.
152  @param exefile Executable to run.
153  @param stdin,stdout Input and output files.
154  """
155  if not os.path.exists(rundir):
156  print("%s does NOT exists " %(rundir))
157  return -999
158  os.chdir(rundir)
159  if not os.path.exists(exefile):
160  print("%s does NOT exists " %(exefile))
161  return -999
162  if nproc <= 1:
163  if os.path.exists(stdin):
164  fin = open(stdin, 'r')
165  else:
166  fin = None
167  with open(rundir+"/std.out", 'w') as fout:
168  try:
169  retcode=subprocess.call(exefile, stdin=fin,stdout=fout)
170  except OSError:
171  print("Failed: (%s)" % exefile )
172  pass
173  return retcode
174  else:
175  with open(rundir+"/std.out", 'w') as fout:
176  runstr="/apps/local/bin/mpiexec -np " + str(nproc) + " " + exefile
177  print(runstr)
178  try:
179  retcode=subprocess.call(runstr, stdout=fout, shell=True)
180  except EnvironmentError as e:
181  print("Failed: (%s): %s" %(exefile, str(e)))
182  pass
183  fout.close()
184  return retcode
185 def read_input(filename):
186  """!Reads the contents of the file for name,value pairs and returns a dict with the contents.
187 
188  Reads the file line-by-line. Searches for pairs of strings
189  "string1,string2" separated by spaces, colons, semicolons or
190  commas. Creates a dict mapping from the first string to the
191  second. Any strings past the second are ignored.
192 
193  @param filename the file to read."""
194  try:
195  input = {}
196  with open(filename, 'rt') as f:
197  for line in f:
198  line=re.split(r'[;,:\s]\s*',line)
199  input[line[1]]=line[0]
200  return input
201  except IOError:
202  print("can NOT open (%s)" %filename)
203 
204 def makenwrap(f):
205  """!Wrapper for making the POM namelist.
206  @param f the return value from pom.nml.make()"""
207  def decoraten(self,DEST):
208  filename = DEST+"/pom.nml"
209  asgn = " = "
210  with open(filename, "w+") as file:
211  arg = "&pom_nml"
212  file.write("%s\n" % (arg))
213  for k in range(len(self.keys)):
214  file.write("\t %s %s %s\n" % (self.keys[k], asgn, \
215  self.namelist[self.keys[k]]))
216  file.write("%s\n" %('/'))
217  return f
218  return decoraten
219 def dateplushours(ymdh, hours):
220  """!Adds a given number of hours to the date.
221  @param ymdh A string "YYYYMMDDHH"
222  @param hours number of hours to add"""
223  if len(ymdh) == 10 and isinstance(ymdh, str) \
224  and isinstance(hours, int):
225  t=datetime.datetime(int(ymdh[0:4]),int(ymdh[4:6]),int(ymdh[6:8]),
226  int(ymdh[8:10]))
227  t+=datetime.timedelta(hours=hours)
228  return t.strftime('%Y%m%d%H')
229  else:
230  print("InputErr: ymdh hours in dateplushours", ymdh, hours)
231 
232 class counter:
233  """!A simple integer counter class."""
234 
235  value = 0
236  def set(self, x):
237  """!Sets the counter value
238  @param x the new counter value"""
239  ##@var value
240  # The current counter value.
241  self.value = x
242  def up(self):
243  """!Increments the counter by 1."""
244  self.value=self.value+1
245  def down(self):
246  """!Decrements the counter by 1."""
247  self.value=self.value-1
248 
249 
250 def logi2int(l):
251  """!Turns a bool to an int, returning 1 for True or 0 for False.
252  @param l the bool value."""
253  assert(type(l) == type(True))
254  if l:
255  return 1
256  else:
257  return 0
258 
259 ##@var jn2r
260 # A synonym for os.path.join
261 jn2r=os.path.join
262 
263 def veto():
264  """!Prints a message about not exiting, and returns False."""
265  try:
266  sys.exit(1)
267  except SystemExit, value:
268  print("caught exit(%s)" % value)
269  return False
270  try:
271  os._exit(2)
272  except SystemExit, value:
273  print("caught exit(%s)" % value)
274  return False
def set(self, x)
Sets the counter value.
Definition: util.py:236
def up(self)
Increments the counter by 1.
Definition: util.py:242
def runexe(nproc, rundir, exefile, stdin, stdout)
Runs an executable.
Definition: util.py:144
def rmall(args)
Deletes a list of files.
Definition: util.py:72
def move
Renames the source file to the destination.
Definition: util.py:104
def link(src, dest)
Links the source file to the destination.
Definition: util.py:128
int value
The current counter value.
Definition: util.py:235
def trailzero(astr, n)
Returns a string of length n or greater, that consists of n-len(astr) zeros followed by astr...
Definition: util.py:46
def logi2int(l)
Turns a bool to an int, returning 1 for True or 0 for False.
Definition: util.py:250
def read_input(filename)
Reads the contents of the file for name,value pairs and returns a dict with the contents.
Definition: util.py:185
def remove(file)
Deletes the specified file.
Definition: util.py:62
def makenwrap(f)
Wrapper for making the POM namelist.
Definition: util.py:204
def down(self)
Decrements the counter by 1.
Definition: util.py:245
def ysplitter(ymdh)
Splits a string with a ten digit YYYYMMDDHH into components.
Definition: util.py:26
A simple integer counter class.
Definition: util.py:232
def inpfile
Creates an input file from a list of strings.
Definition: util.py:51
def veto()
Prints a message about not exiting, and returns False.
Definition: util.py:263
def dateplushours(ymdh, hours)
Adds a given number of hours to the date.
Definition: util.py:219
def copy
Copies the source to the destination without retaining permissions our group IDs. ...
Definition: util.py:77