0

I have a script that's asking the user to input a lot of dates, mostly in functions similar to the one below. These need to account for invalid date formats:

import numpy as np
import pandas as pd
import xlwings as xw
import datetime as dtt

def week_init():
        """Creates an initial week datetime and determines what the checking cutoff
        'beforeday' to be used in Stage 2 is."""
        week = input('Week to check: MM/DD/YYYY\n')
        switch = 1
        while switch == 1:
            try:
                week = dtt.datetime.strptime(week,'%m/%d/%Y') #turns input to a datetime
                switch = 0
            except ValueError:
                week = input('Unrecognized date format, please try again: MM/DD/YYYY\n')
        beforeday = (input('Check days before date (Press enter to use today): MM/DD/YYYY\n')
            or dtt.date.today())
        if (beforeday != dtt.date.today()):
            switch = 1
            while switch == 1:
                try:
                    beforeday = dtt.datetime.strptime(beforeday,'%m/%d/%Y')
                    switch = 0
                except ValueError:
                    beforeday = input('Unrecognized date format, please try again: MM/DD/YYYY\n')
        return week, beforeday

There are also functions that check an index for a given date, and have to deal with a given date not matching any of the indices:

def spotmap(week, bam, pt):
    """Maps the pivoted data for the chosen week to the BAM dataframe's SD column."""
    print('Mapping data to BAM... ',end=''),
    switch = 1
    while switch == 1:
        try:
            bam['SD'] = bam.index.to_series().map(pt.fillna(0)['len',week])
            switch = 0
        except KeyError:
            print('Invalid date, please try again.')
            week = input('Week start date (Sunday): MM/DD/YYYY\n')
    print('Done')
    return bam

As the script has a lot of things to do after it gets these dates, I don't want it to crash when it has a problem, but it can't proceed without correct date inputs so I currently have it looping with those "switch" variables controlling when it is willing to move on with a valid date. As you can see, though, these try/except blocks are rapidly bloating the otherwise straightforward code. Is there a way to condense these things? Also, a better method than the switches?

Repetitive Try and Except Clauses

The answers here suggested decorators, but as far as I can tell from the documentation and pages like this, those are for wrapping functions, not for replacing interior code blocks. Also I'm not sure how useful they'd be, because the try/except blocks are mostly unique in what they're trying to accomplish (ie, which variable they're changing). I guess I'm really just hoping for some better syntax.

Steve R
  • 131
  • 2
  • 11

1 Answers1

0

Try wrapping up your repeated calls in functions to decrease the bloat. Here's a stab at it:

import numpy as np
import pandas as pd
import xlwings as xw
import datetime as dtt

def loop_until_good(func, arg):
    looping = True
    while looping:
        (arg, looping) = func(arg)
        return arg

def make_datetime(date):
    try:
        date = dtt.datetime.strptime(date,'%m/%d/%Y') #turns input to a datetime
        return date, False
    except ValueError:
        date = input('Unrecognized date format, please try again: MM/DD/YYYY\n')
        return date, True

def bammit(arg):
    (bam, week, pt) = arg
    try:
        bam['SD'] = bam.index.to_series().map(pt.fillna(0)['len',week])
        return (bam, week, pt), False
    except KeyError:
        print('Invalid date, please try again.')
        week = input('Week start date (Sunday): MM/DD/YYYY\n')
        return (bam, week, pt), True

def week_init():
        """Creates an initial week datetime and determines what the checking cutoff
        'beforeday' to be used in Stage 2 is."""
        week = str(input('Week to check: MM/DD/YYYY\n'))
        print type(week)
        print week
        loop_until_good(make_datetime, week)
        beforeday = (input('Check days before date (Press enter to use today): MM/DD/YYYY\n')
            or dtt.date.today())
        if (beforeday != dtt.date.today()):
            loop_until_good(make_datetime, beforeday)
        return week, beforeday

def spotmap(week, bam, pt):
    """Maps the pivoted data for the chosen week to the BAM dataframe's SD column."""
    print('Mapping data to BAM... ')
    loop_until_good(bammit, (bam, week, pt))
    print('Done')
    return bam
mugwump
  • 436
  • 1
  • 4
  • 10