最初我想做类似的事情:
#EXIT CODES
class ExitCode(object):
(USERHOME_INVALID, \
USERHOME_CANNOT_WRITE, \
USERHOME_CANNOT_READ, \
BASHRC_INVALID) = range(-1, -5, -1)
但是我已经意识到我必须确切地知道EXIT_CODES的总数,以便我可以将它传递给range()函数。假设我有87个(任意的)EXIT_CODES ......我不想数到87(不是很难),但我正在寻找更优雅的解决方案。
有什么建议吗?
编辑: EXIT_CODE是一个负int,将传递给sys.exit。而不是写数字我更喜欢使用某种常量(如C中的#defines或枚举,或Java中的枚举)。
答案 0 :(得分:2)
听起来你想要的是Python等同于C#或其他类似语言中的枚举。 How can I represent an 'Enum' in Python?提供了多种解决方案,但它们仍然需要您拥有的项目数量。 编辑:How can I represent an 'Enum' in Python?看起来方式更好。
或者你可以尝试这样的事情(可能不是最好的解决方案):
class _ExitCode:
_exit_codes=["EXIT_CODE","EXIT_CODE_TWO"]
def __getattr__(self, name):
if name in _ExitCode._exit_codes:
return -(_ExitCode._exit_codes.index(name)+1)
raise AttributeError("Exit code %s not found" % name)
ExitCode=_ExitCode()
print ExitCode.EXIT_CODE #-1
答案 1 :(得分:1)
也许我不理解这个问题,但为什么不简单地编写退出代码字典并在函数中实现所需的行为?
EXIT_CODES = dict(SUCCESS=0,
USER_NAME_INVALID=-1,
OTHER_ERROR=-2)
def exit(code):
try:
return EXIT_CODES[code]
except KeyError:
raise KeyError("exit code %s is not implemented" % code)
所以你可以像
一样使用它# some computation goes here
return exit("SUCCESS")
如果你想对数字进行“自动”分配(我不建议这样做)你可以简单地创建一个退出代码列表并返回索引的负数:
EXIT_CODES = ['SUCCESS', 'ERROR_1', 'ERROR_2']
return -EXIT_CODES.index('ERROR_1')
# will return -1
(对于最后一个,你可以实现类似于基于字典的功能)
答案 2 :(得分:1)
我必须注意到,对于sys.exit()来说,负面状态根本不合理。至少在Linux上,它将被解释为无符号的8位值(范围0-255)。对于枚举类型,可以执行以下操作:
class ExitStatus: pass
for code, name in enumerate("Success Failure CriticalFailure".split()):
setattr(ExitStatus, name, code)
导致类似:
>>> ExitStatus.__dict__
{'CriticalFailure': 2, 'Failure': 1, '__module__': '__main__',
'__doc__': None, 'Success': 0}
普通Unix系统中的预定义值为EXIT_FAILURE = 1且EXIT_SUCCESS = 0。
附录:考虑到IDE识别标识符的问题,人们也可以这样做:
class EnumItem: pass
def adjustEnum(enum):
value=0
enumdict=enum.__dict__
for k,v in enumdict.items():
if isinstance(v,int):
if v>=value:
value=v+1
for k,v in enumdict.items():
if v is EnumItem:
enumdict[k]=value
value+=1
class ExitStatus:
Success=0
Failure=EnumItem
CriticalFailure=EnumItem
adjustEnum(ExitStatus)
第二次编辑:无法远离。这是一个变体,它按照您编写名称的顺序分配值。
class EnumItem:
serial=0
def __init__(self):
self.serial=self.__class__.serial
self.__class__.serial+=1
def adjustEnum(enum):
enumdict=enum.__dict__
value=0
unknowns={}
for k,v in enumdict.items():
if isinstance(v,int):
if v>=value:
value=v+1
elif isinstance(v,EnumItem):
unknowns[v.serial]=k
for i,k in sorted(unknowns.items()):
enumdict[k]=value
value+=1
return enum
@adjustEnum
class ExitStatus:
Success=0
Failure=EnumItem()
CriticalFailure=EnumItem()
显然,日益增加的复杂性是不优雅的,但确实有效。
答案 3 :(得分:1)
我想我之前看过这个问题并没有看到它,但一个显而易见的事情是使用dict。
def make_exit_codes(*exit_codes):
return dict((name, -value - 1) for name, value in enumerate(exit_codes))
EXIT_CODES = make_exit_codes('USERHOME_INVALID', 'USERHOME_CANNOT_WRITE',
'USERHOME_CANNOT_READ', 'BASHRC_INVALID')
答案 4 :(得分:0)
您可以使用Python即时创建变量(或类属性)。例如
ExitCodes = '''USERHOME_INVALID, USERHOME_CANNOT_WRITE,
USERHOME_CANNOT_READ, BASHRC_INVALID'''
for i, s in enumerate(ExitCodes.split(','), 1):
exec('%s = %d' % (s.strip(), -i))
print USERHOME_INVALID
print USERHOME_CANNOT_WRITE
print USERHOME_CANNOT_READ
print BASHRC_INVALID
sys.exit(USERHOME_INVALID)
>>> -1
>>> -2
>>> -3
>>> -4