您如何实施';退出代码';用python?

您如何实施';退出代码';用python?,python,exit-code,Python,Exit Code,起初我想做一些事情,比如: #EXIT CODES class ExitCode(object): (USERHOME_INVALID, \ USERHOME_CANNOT_WRITE, \ USERHOME_CANNOT_READ, \ BASHRC_INVALID) = range(-1, -5, -1) class ExitStatus: pass for code, name in enumerate("Success Failure CriticalF

起初我想做一些事情,比如:

#EXIT CODES
class ExitCode(object):
    (USERHOME_INVALID, \
    USERHOME_CANNOT_WRITE, \
    USERHOME_CANNOT_READ, \
    BASHRC_INVALID) = range(-1, -5, -1)
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}
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)
但是我意识到,我必须准确地知道EXIT_代码的总数,这样我才能将它传递给range()函数。假设我有87个(任意)退出代码。。。我不想数到87(这并不难),但我正在寻找一个更优雅的解决方案

有什么建议吗

编辑:
EXIT_代码是将传递给sys.EXIT的负整数。与其写数字,我更喜欢使用某种常量(比如C中的#defines或enum,或者Java中的enum)。

听起来你想要的是与C或其他类似语言中的枚举相当的Python。提供多种解决方案,尽管它们仍然需要您拥有的项目数量。 编辑:看起来好多了

或者您可以尝试类似的方法(但可能不是最好的解决方案):


也许我不明白这个问题,但为什么不简单地编写一个退出代码字典,并在函数中实现所需的行为呢

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

(对于最后一个,您可以实现一个与基于字典的函数类似的函数)

我必须注意,对于sys.exit(),根本不确定负状态是否有意义;至少在Linux上,它将被解释为无符号8位值(范围0-255)。对于枚举类型,可以执行以下操作:

#EXIT CODES
class ExitCode(object):
    (USERHOME_INVALID, \
    USERHOME_CANNOT_WRITE, \
    USERHOME_CANNOT_READ, \
    BASHRC_INVALID) = range(-1, -5, -1)
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}
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)
结果是:

#EXIT CODES
class ExitCode(object):
    (USERHOME_INVALID, \
    USERHOME_CANNOT_WRITE, \
    USERHOME_CANNOT_READ, \
    BASHRC_INVALID) = range(-1, -5, -1)
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}
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)
正常Unix系统中的预定义值为EXIT_FAILURE=1和EXIT_SUCCESS=0

附录:考虑到IDE标识标识符的问题,还可以做如下操作:

#EXIT CODES
class ExitCode(object):
    (USERHOME_INVALID, \
    USERHOME_CANNOT_WRITE, \
    USERHOME_CANNOT_READ, \
    BASHRC_INVALID) = range(-1, -5, -1)
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}
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()
显然,日益增长的复杂性是不雅观的,但它确实有效。

您可以使用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

我想我之前看过这个问题,但没有看到,但一件显而易见的事情是使用口述

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')

只是一个注释-你不需要括号中的反斜杠。这并不重要,但它们是多余的,不是真正的“Pythonic”。问题是dict包含的值会自动递增。我不想手动写入0,-1,-2,…,-87,然后意识到我必须重新组合它们。请不要过于急切地使用exec()之类的东西。您可能也可以使用
globals()。\uuuuu setitem\uuuu(s,-i)
。如果没有其他人对它进行了投票,那么这不值得投下一票,但是使用
exec
应该位于列表的底部。l33tnerd的解决方案要优雅得多。“愚蠢的一致性是小头脑的妖怪……”这意味着,我相信,你可以根据具体情况自己决定。我实际上喜欢这个解决方案。缺点是我当前使用的IDE(Eclipse和PyDev)无法识别执行变量,因为它们是在运行时声明的。@Andrei Ciobanu。从未想过这一点——我猜需要一个非常智能的Python感知IDE来识别在运行时创建的标识符,在某些情况下甚至不可能。然而,我怀疑你所说的对目前发布的大多数答案也是正确的。感谢您指出另一个需要考虑的权衡。