【发布时间】:2014-12-13 21:48:56
【问题描述】:
我正在使用argparse 模块通过命令行创建地址对象。但是当我给它提供无效参数(即那些应该引发异常的参数)时,不会引发任何异常。更糟糕的是,没有记录任何内容(除非我创建了一个有效的对象)。
所以,这行得通:
-n Patrick -a "151 Piedmont Ave" -c "Winston Salem" -s "NC" -z 27101
这不是:
-l ERROR -n Patrick -a "151 Piedmont Ave" -c "Winston Salem" -s "NC" -z 271
我哪里错了?
注意:这是家庭作业,因此非常感谢您对绝对答案的指导。
"""
property_address.py
"""
import re
import logging
import argparse
LOG_FILENAME = 'property_address.log'
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(funcName)s - %(message)s"
DEFAULT_LOG_LEVEL = "debug"
LEVELS = {'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL
}
def start_logging(filename=LOG_FILENAME, level=None):
logging.basicConfig(filename=filename, level=level, filemode='w', format=LOG_FORMAT)
logging.info('Starting up the property address program')
class ZipCodeError(Exception):
"Custom exception for invalid zip codes."
pass
class StateError(Exception):
"Custom exception for invalid state abbreviation."
pass
class Address(object):
"""
An address object.
"""
def __init__(self, name, street_address, city, state, zip_code):
self._name = name
self._street_address = street_address
self._city = city
self._state = state
self._zip_code = zip_code
logging.info('Instantiated an address')
@property
def name(self):
return self._name
@property
def street_address(self):
return self._street_address
@property
def city(self):
return self._city
@property
def state(self):
return self._state
@state.setter
def state(self, value):
"Validate that states are abbreviated as US Postal style."
state_valid = re.compile(r'[A-Z]{2}$')
if re.match(state_valid, value):
self._state = value
else:
message = 'STATE Exception: State not in correct format'
logging.error(message)
raise StateError()
@property
def zip_code(self):
return self._zip_code
@zip_code.setter
def zip_code(self, value):
"Validate zip codes are five digits."
zip_valid = re.compile(r'\d{5}$')
if re.match(zip_valid, value):
self._zip_code = value
else:
message = 'ZIP CODE Exception: Zip code not in correct format'
logging.error(message)
raise ZipCodeError()
def __str__(self):
return self._name
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Set attributes for property address.')
parser.add_argument(
'-l',
'--level',
dest='level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO',
help='Sets the log level to DEBUG, INFO, WARNING, ERROR, and CRITICAL')
parser.add_argument(
'-n',
'--name',
dest='name',
action='store',
required=True,
help='Sets the name value of the Address object')
parser.add_argument(
'-a',
'--address',
dest='address',
action='store',
required=True,
help='Sets the street_address value of the Address object')
parser.add_argument(
'-c',
'--city',
dest='city',
action='store',
required=True,
help='Sets the city value of the Address object')
parser.add_argument(
'-s',
'--state',
dest='state',
action='store',
required=True,
help='Sets the state value of the Address object')
parser.add_argument(
'-z',
'--zip_code',
dest='zip_code',
action='store',
required=True,
help='Sets the zip_code value of the Address object')
args = parser.parse_args()
# Start our logger
start_logging(level=(args.level))
# Create our Address object
a = Address(args.name, args.address, args.city, args.state, args.zip_code)
【问题讨论】:
-
为什么不将邮政编码作为参数的一部分进行测试;参见例如stackoverflow.com/q/25470844/3001761
-
这是有道理的。但是为什么我的异常一开始没有被提出呢?
-
因为在
Address.__init__中,您分配给self._zip_code,绕过了setter,而不是self.zip_code。 -
另外,你应该更加一致;
zip_code和state可以更改,但其他属性是只读的。要么将检查放入__init__并将它们全部设为只读,要么将它们保留为普通属性并放弃它们的吸气剂。 Python 可以很容易地在以后将它们放回原处。 -
好点。看起来这里也有一个很好的属性解释:chimera.labs.oreilly.com/books/1230000000393/…
标签: logging argparse python-3.4