How do you implement 'EXIT_CODES' in python?
Initially i thought to do something like:
#EXIT CODES
class开发者_StackOverflow ExitCode(object):
(USERHOME_INVALID, \
USERHOME_CANNOT_WRITE, \
USERHOME_CANNOT_READ, \
BASHRC_INVALID) = range(-1, -5, -1)
But than I've realized that I'll have to know exactly the total number of EXIT_CODES, so that I can pass it to the range() function. Let's suppose I'll have 87 (arbitrary) EXIT_CODES... I don't want to count to 87 (not that it's hard) but I am looking for a more elegant solution.
Any suggestions ?
EDIT: EXIT_CODE is a negative int that will be passed to sys.exit . Instead of writing the number I prefer to use some sort of constants (something like #defines or enums in C, or enums in Java).
Sounds like what you want is the Python equivalent of an enumeration in C# or other similar languages. How can I represent an 'Enum' in Python? provides several solutions, though they still require the number of items you have. EDIT: How can I represent an 'Enum' in Python? looks way better.
Or you could try something like this (probably not the best solution, though):
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
Maybe I don't understand the question, but why don't you simply make a dictionary of exit codes and implement the desired behaviour in a function?
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)
So you can use it like
# some computation goes here
return exit("SUCCESS")
And if you want to make "automatic" assignment of numbers (I don't recommend this) you can simply create a list of exit codes and return the negative of the index:
EXIT_CODES = ['SUCCESS', 'ERROR_1', 'ERROR_2']
return -EXIT_CODES.index('ERROR_1')
# will return -1
(for the last one, you can implement a function similar to the dictionary-based one)
I must note that it's not at all certain a negative status makes sense for sys.exit(); at least on Linux, it will be interpreted as an unsigned 8-bit value (range 0-255). As for an enumerated type, it's possible to do something like:
class ExitStatus: pass
for code, name in enumerate("Success Failure CriticalFailure".split()):
setattr(ExitStatus, name, code)
Resulting in something like:
>>> ExitStatus.__dict__
{'CriticalFailure': 2, 'Failure': 1, '__module__': '__main__',
'__doc__': None, 'Success': 0}
The predefined values in normal Unix systems are EXIT_FAILURE=1 and EXIT_SUCCESS=0.
Addendum: Considering the concern about IDE identification of identifiers, one could also do something like:
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)
Second edit: Couldn't keep away. Here's a variant that assigns the values in the order you've written the names.
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()
Obviously the growing complexity is inelegant, but it does work.
I guess I looked at this question earlier and didn't see it, but one obvious thing to do is use a 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')
You can create variables (or class attributes) on-the-fly with Python. For example
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
精彩评论