正则匹配时间格式失败引发AttributeError而非ValueError的原因
问题分析:输入无空格时间字符串触发AttributeError的原因及修复
问题描述
我希望convert函数能验证格式为“9 AM to 5 PM”或“9:00 AM to 5:00 PM”的字符串,当时间与AM/PM之间无空格(例如“9AM to 5PM”)或格式错误时,抛出ValueError。但实际输入“9AM to 5PM”时,却触发了AttributeError,提示'NoneType'对象没有'group'属性,请问这是为什么?
现有代码如下:
import re import sys def main(): try: print(convert(input("Hours: "))) except ValueError: print("Invalid format. Please use '9:00 AM to 5:00 PM' or '9 AM to 5 PM'.") def convert(s): matches = re.search(r"^([0-9]+):?([0-9]+)? (AM|PM) to ([0-9]+):?([0-9]+)? (AM|PM)$", s) hour1 = int(matches.group(1)) minute1 = int(matches.group(2) or 0) hour2 = int(matches.group(4)) minute2 = int(matches.group(5) or 0) am_pm1 = matches.group(3).upper() am_pm2 = matches.group(6).upper() if matches: if hour1 > 12 or hour2 > 12 or minute1 > 59 or minute2 > 59: raise ValueError if hour1 == 12 and am_pm1 == "AM": hour1 = 0 elif hour1 != 12 and am_pm1 == "PM": hour1 += 12 if hour2 == 12 and am_pm2 == "AM": hour2 = 0 elif hour2 != 12 and am_pm2 == "PM": hour2 += 12 else: raise ValueError time1 = f"{hour1:02}:{minute1:02}" time2 = f"{hour2:02}:{minute2:02}" return time1 + " to " + time2 if __name__ == "__main__": main()
错误原因
核心问题是正则匹配失败后直接调用了matches.group()方法:
- 当输入“9AM to 5PM”时,你的正则表达式要求时间数字与AM/PM之间必须有空格,但输入中没有这个空格,导致
re.search()无法匹配,返回None。 - 代码中先执行了
matches.group(1)等分组提取操作,之后才检查matches是否有效。此时matches是None,调用group()方法自然会触发AttributeError,而不是预期的ValueError。
修复方案
调整代码执行顺序,先验证正则匹配结果,再提取分组内容:
- 在调用任何
matches.group()之前,先判断matches是否不为None,如果匹配失败直接抛出ValueError。 - 移除原代码中冗余的
else分支,提前的判断已经覆盖了匹配失败的场景。
修正后的完整代码
import re import sys def main(): try: print(convert(input("Hours: "))) except ValueError: print("Invalid format. Please use '9:00 AM to 5:00 PM' or '9 AM to 5 PM'.") def convert(s): matches = re.search(r"^([0-9]+):?([0-9]+)? (AM|PM) to ([0-9]+):?([0-9]+)? (AM|PM)$", s) # 先检查匹配结果,失败直接抛出ValueError if not matches: raise ValueError # 匹配成功后再提取分组内容 hour1 = int(matches.group(1)) minute1 = int(matches.group(2) or 0) hour2 = int(matches.group(4)) minute2 = int(matches.group(5) or 0) am_pm1 = matches.group(3).upper() am_pm2 = matches.group(6).upper() # 验证时间数值的合法性 if hour1 > 12 or hour2 > 12 or minute1 > 59 or minute2 > 59: raise ValueError if hour1 == 12 and am_pm1 == "AM": hour1 = 0 elif hour1 != 12 and am_pm1 == "PM": hour1 += 12 if hour2 == 12 and am_pm2 == "AM": hour2 = 0 elif hour2 != 12 and am_pm2 == "PM": hour2 += 12 time1 = f"{hour1:02}:{minute1:02}" time2 = f"{hour2:02}:{minute2:02}" return time1 + " to " + time2 if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者testtest
相关产品推荐
相关产品推荐

