Q's on my first python script

Nick Craig-Wood nick at craig-wood.com
Mon May 11 11:30:04 CEST 2009


kj <socyl at 987jk.com.invalid> wrote:
> 
>  Below is my very firs python script.
> 
>  This was just a learning exercise; the script doesn't do anything
>  terribly exciting: for an argument of the form YYMMDD (year, month,
>  day) it prints out the corresponding string YYMMDDW, where W is a
>  one-letter abbreviation for the day of the week.  E.g.
> 
>  % wd 090511
>  090511M
> 
>  The script runs OK, but I can still see a few areas of improvement,
>  for which I could use your advice.
> 
>  1. The name of the BadArgument exception class defined in the script
>     does not seem to me sufficiently specific.  If one were to import
>     the script in order to reuse its wkday_abbrev function, I'd like
>     this exception's name to be more unequivocally tied to this
>     script.  What I'm looking for is something like a "namespace"
>     for this script.  What's the pythonic way to construct a namespace?
> 
>  2. In some python modules I've seen the idiom
> 
>     if __name__ == "__main__":
>        # run some tests here
> 
>     I'd like to set up tests for this script, mostly to ensure that
>     it handles the error cases properly, but I'm alread using the
>     idiom above to actually run the script under normal operation.
>     What's the typical python idiom for running tests on a *script*
>     (as opposed to a module that is normally not supposed to be run
>     directly)?
> 
>  3. Still on the subject of testing, how does one capture in a
>     variable the output that would normally have gone to stdout or
>     stderr?
> 
>  4. What's the python way to emit warnings?  (The script below should
>     warn the user that arguments after the first one are ignored.)
> 
>  5. The variable wd is meant to be "global" to the script.  In other
>     languages I've programmed in I've seen some typographic convention
>     used for the name of such variables (e.g. all caps) to signal
>     this widened scope.  Does python have such a convention?
> 
>  Any comments/suggestions on these questions, or anything else about
>  the script, would be much appreciated.

To be honest, my first try at this script probably would have looked
quite like yours!  Once it was working I'd have tidied it as below.

  * Put into a class to stop spread of globals
  * WD made class member and upper case
  * 4 space indents as per PEP8
  * remove lamda as it isn't needed
  * only try:/except: the minimum possible amount of code
  * new name for exception


from optparse import OptionParser
import re
import datetime
import sys

class BadDateString(Exception):
    """Malformed date string"""

class Main(object):
    """Script to implement weekday"""
    WD = ("M", "T", "W", "H", "F", "S", "U")
    def wkday_abbrev(self, date_string):
        mm = re.match("(\d{2})(\d{2})(\d{2})\Z", date_string)
        if not mm:
            raise BadDateString("Couldn't match date string from %r" % date_string)
        y, m, d = map(int, mm.groups())
        if y < 38:
            y = y + 1900
        else:
            y = y + 2000
        try:
            return self.WD[datetime.datetime(y, m, d).weekday()]
        except ValueError:
            raise BadDateString("Bad date in %r" % date_string)

    def __init__(self):
        usage = '''Usage: %prog [options] YYMMDD
           %prog -h|--help
'''
        parser = OptionParser(usage=usage)
        parser.add_option("-n", "--no-newline", dest="nonl",
                          action="store_true", help="omit newline in output")
        (options, args) = parser.parse_args();
        try:
            weekday = self.wkday_abbrev(args[0])
        except BadDateString, e:
            print usage
            print e
            sys.exit(1)
        sys.stdout.write("%s%s" % (args[0], weekday))
        if not options.nonl:
            print

if __name__ == "__main__":
    Main()

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list