简体   繁体   English

Python:在另一个函数中调用具有返回值的函数:错误处理?

[英]Python: Calling a function inside another function with returned values: Error Handling?

I have created the following Python module that converts 24hr time (00:00 to 23:59) into words. 我创建了以下Python模块,该模块将24小时(00:00到23:59)转换为单词。 Function1() tests that the input string matches the correct 24hr format before trying to extract the 12hours, minutes and period (ie am = 'before midday' and pm = 'after midday'). Function1()在尝试提取12小时,分钟和句点之前测试输入的字符串是否与正确的24小时格式匹配(即am =“中午之前”和pm =“中午之后”)。 The following works perfectly as a standalone function, but fails when I call it from function3() when the input string doesn't match the correct format and the try statement doens't execute therefore the return values are not returned. 下面的代码可以完美地用作一个独立的函数,但是当我从function3()调用它时,当输入字符串与正确的格式不匹配并且try语句不执行时,失败,因此不会返回返回值。 Function3() therefore fails as the following return values don't exist. 由于以下返回值不存在,因此Function3()失败。 How do I restructure function1() so that if the pattern doesn't match, the Python module stops running and only executes the else statement in function1() letting the end user know that the input string doesn't match the correct format? 如何重组function1(),以便在模式不匹配时,Python模块停止运行,仅执行function1()中的else语句,让最终用户知道输入字符串与正确的格式不匹配?

"""
Created on 29 May 2017

Convert 24hr format time

into time as words

@author: PeterW
"""
# import site-packages and modules
import re
import time
import argparse


def function1(input_time):
    """convert time from 24hr format
    into 12hours, minutes, period"""
    period_type = {'AM': 'before midday', 'PM': 'after midday'}
    regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
    if regexp_object.match(input_time):
        try:
            time_object = time.strptime(input_time, '%H:%M')
            suffix = time.strftime('%p', time_object)
            hours = int(time.strftime('%I', time_object))
            minutes = time_object[4]
            period = period_type.get(suffix)
            print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
            return hours, minutes, period
        except ValueError as err:
            print(err)
    else:
        print("{0} doesn't match required format 00:00 to 23:59"
              .format(input_time))


def function2():
    """create dictionary
    to lookup equivalent word
    of integer number"""
    words_lookup = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
                    6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
                    11: 'eleven', 12: 'twelve', 13: 'thirteen',
                    14: 'fourteen', 16: 'sixteen', 17: 'seventeen',
                    18: 'eighteen', 19: 'nineteen', 20: 'twenty',
                    21: 'twenty one', 22: 'twenty two', 23: 'twenty three',
                    24: 'twenty four', 25: 'twenty five', 26: 'twenty six',
                    27: 'twenty seven', 28: 'twenty eight', 29: 'twenty nine'}
    return words_lookup


def function3(input_time):
    """convert 24hr format time
    into time as words"""
    hours, minutes, period = function1(input_time)
    words_lookup = function2()
    if hours == 12:
        hours2 = words_lookup.get(1)
    else:
        hours2 = words_lookup.get(hours+1)
    if hours == 12 and minutes == 0 and period == 'before midday':
        time = 'Midnight'
    elif hours == 12 and minutes == 0 and period == 'after midday':
        time = 'Midday'
    elif minutes == 0:
        time = "{0} o'clock {1}.".format(str(words_lookup.get(hours)).title(),
                                         period)
    elif minutes == 15:
        time = "Quarter past {0} {1}.".format(words_lookup.get(hours),
                                              period)
    elif minutes == 30:
        time = "Half past {0} {1}.".format(words_lookup.get(hours),
                                           period)
    elif minutes == 45:
        time = "Quarter to {0} {1}.".format(hours2,
                                            period)
    elif minutes < 30:
        minutes = str(words_lookup.get(minutes)).capitalize()
        time = "{0} minutes past {1} {2}.".format(minutes,
                                                  words_lookup.get(hours),
                                                  period)
    else:
        minutes = str(words_lookup.get(60 - minutes)).capitalize()
        time = '{0} minutes to {1} {2}.'.format(minutes,
                                                hours2,
                                                period)
    print(time)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Convert 24hr format time into time as words")
    parser.add_argument('--input_time', metavar='string', required=True,
                        help='input time in following format 00:00 to 23:59')
    args = parser.parse_args()
    function3(input_time=args.input_time)

Final version below, thanks for the help. 最终版本如下,感谢您的帮助。

"""
Created on 04 June 2017

Convert 24hr format time

into time as words

@author: PeterW
"""
# import site-packages and modules
import sys
import re
import time
import argparse


def validate_time_format(input_time):
    """Validate that input string
    matches require 24hr time format"""
    regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
    if regexp_object.match(input_time):
        print("Processing: {0} into words".format(input_time))
        time_str = input_time
    else:
        print("{0} doesn't match required input format: 00:00 to 23:59".format(input_time))
        sys.exit()
    return time_str


def extract_time(time_str):
    """convert time from 24hr format
    into 12hours, minutes, period"""
    period_type = {'AM': 'before midday', 'PM': 'after midday'}
    try:
        time_object = time.strptime(time_str, '%H:%M')
        suffix = time.strftime('%p', time_object)
        hours = int(time.strftime('%I', time_object))
        minutes = time_object[4]
        period = period_type.get(suffix)
#         print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
        return hours, minutes, period
    except ValueError as err:
        print(err)


def time_lookup():
    """create dictionary
    to lookup equivalent word
    of integer number"""
    words_lookup = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
                    6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
                    11: 'eleven', 12: 'twelve', 13: 'thirteen',
                    14: 'fourteen', 16: 'sixteen', 17: 'seventeen',
                    18: 'eighteen', 19: 'nineteen', 20: 'twenty',
                    21: 'twenty one', 22: 'twenty two', 23: 'twenty three',
                    24: 'twenty four', 25: 'twenty five', 26: 'twenty six',
                    27: 'twenty seven', 28: 'twenty eight', 29: 'twenty nine'}
    return words_lookup


def time_as_words(input_time):
    """convert 24hr format time
    into time as words"""
    time_str = validate_time_format(input_time)
    hours, minutes, period = extract_time(time_str)
    words_lookup = time_lookup()
    if hours == 12:
        hours2 = words_lookup.get(1)
    else:
        hours2 = words_lookup.get(hours+1)
    if hours == 12 and minutes == 0 and period == 'before midday':
        time = 'Midnight'
    elif hours == 12 and minutes == 0 and period == 'after midday':
        time = 'Midday'
    elif minutes == 0:
        time = "{0} o'clock {1}.".format(str(words_lookup.get(hours)).title(),
                                         period)
    elif minutes == 15:
        time = "Quarter past {0} {1}.".format(words_lookup.get(hours),
                                              period)
    elif minutes == 30:
        time = "Half past {0} {1}.".format(words_lookup.get(hours),
                                           period)
    elif minutes == 45:
        time = "Quarter to {0} {1}.".format(hours2,
                                            period)
    elif minutes < 30:
        min_str = str(words_lookup.get(minutes)).capitalize()
        time = "{0} minute{1} past {2} {3}.".format(min_str,
                                                    "" if minutes == 1 else "s",
                                                    words_lookup.get(hours),
                                                    period)
    else:
        min_str = str(words_lookup.get(60 - minutes)).capitalize()
        time = '{0} minute{1} to {2} {3}.'.format(min_str,
                                                  "" if 60 - minutes == 1 else "s",
                                                  hours2,
                                                  period)
    print(time)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Convert 24hr format time into time as words")
    parser.add_argument("-t", "--input_time", metavar="time", type=str, required=True,
                        help='input time in the following format 00:00 to 23:59')
    args = parser.parse_args()
    time_as_words(input_time=args.input_time)

When your function1 fails, it implicitly returns a None . function1失败时,它隐式返回None The caller has to be aware of this possibility: 呼叫者必须意识到这种可能性:

retval = function1(input_time)
if retval is None:
    # do something - say, exit
else:
    hours, minutes, period = retval

Switch the if regexp_object.match(input_time) for an if not regexp_object.match(input_time) , and switch the logic around too: if regexp_object.match(input_time)切换为if not regexp_object.match(input_time) ,并同时切换逻辑:

def function1(input_time):
    """convert time from 24hr format
    into 12hours, minutes, period"""
    period_type = {'AM': 'before midday', 'PM': 'after midday'}
    regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
    # Switch to checking if it isn't valid instead, and exit early if that's the case
    if not regexp_object.match(input_time):
        print("{0} doesn't match required format 00:00 to 23:59"
              .format(input_time))
        exit(-1)

    # Since we already returned if the regex didn't match, we know if it reaches this point it'll match
    try:
        time_object = time.strptime(input_time, '%H:%M')
        suffix = time.strftime('%p', time_object)
        hours = int(time.strftime('%I', time_object))
        minutes = time_object[4]
        period = period_type.get(suffix)
        print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
        return hours, minutes, period
    except ValueError as err:
        print(err)

Note that exit actually exits the program altogether. 请注意, exit实际上是完全退出程序。 If you merely wanted to return something (such as None , to sign that something went wrong) to a further function, you could instead do return None and the function would return then and there. 如果您只想将某个内容(例如None ,以表示出现问题)返回到另一个函数,则可以改return None然后该函数将在那儿返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM