跨模块的Python枚举

DCT*_*Lib 11 python enums module

如果在主模块中定义了枚举,为什么不能跨模块边界正确检查Python 3枚举等式?这是一个例子:

moduleA.py:

#!/usr/bin/python3

import moduleB
from enum import Enum, unique

@unique
class MyEnum(Enum):
    A = 1
    B = 2
    # def __eq__(self,other):
    #     assert isinstance(other,self.__class__)
    #     return self.value == other.value

if __name__ == "__main__":

    myVar = MyEnum.B
    moduleB.doStuff(myVar)
Run Code Online (Sandbox Code Playgroud)

moduleB.py:

#!/usr/bin/python3

import moduleA

def doStuff(aVariable):
    bVariable = moduleA.MyEnum.B
    assert aVariable == bVariable
Run Code Online (Sandbox Code Playgroud)

在命令行上调用" ./moduleA.py "会产生:

Traceback (most recent call last):
  File "./moduleA.py", line 17, in <module>
    moduleB.doStuff(myVar)
  File "/home/ruedi/Dropbox/Reps/stuffed/sosy/testing/moduleB.py", line 7, in doStuff
    assert aVariable == bVariable
AssertionError
Run Code Online (Sandbox Code Playgroud)

取消注释枚举中的自定义相等运算符会导致断言失败.我发现在两种情况下类模块都不一样,因为在一种情况下它是"__main__".

解决这个问题的最"Pythonic方式"是什么(除了将枚举移动到自己的模块之外)?

编辑:切换到"aVariable是bVariable"也不起作用:

Traceback (most recent call last):
  File "./moduleA.py", line 17, in <module>
    moduleB.doStuff(myVar)
  File "/home/ruedi/Dropbox/Reps/stuffed/sosy/testing/moduleB.py", line 7, in doStuff
    assert aVariable is bVariable
AssertionError
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 17

就Python而言,这里有三个模块:

  • __main__
  • moduleA
  • moduleB

从命令行(主入口点)运行的文件始终存储为__main__模块.如果您moduleA在代码中的任何位置导入,Python会将其视为与__main__模块分开,而是创建一个新的模块对象.因此,您有两个单独的MyEnum类:

  • __main__.MyEnum
  • moduleA.MyEnum

他们的成员是截然不同的,因此不能平等.

您的测试通过了,而不是使用import moduleA您使用import __main__ as moduleA,或使用单独的脚本文件来驱动测试; 单独的文件将成为__main__:

#!/usr/bin/python3
# test.py, separate from moduleA.py and moduleB.py

import moduleA    
import moduleB

if __name__ == "__main__":
    myVar = moduleA.MyEnum.B
    moduleB.doStuff(myVar)
Run Code Online (Sandbox Code Playgroud)

另一个解决办法是来告诉Python这__main__moduleA是一样的; 导入moduleA(或moduleB导入moduleA)之前,您可以添加另一个条目sys.modules:

if __name__ == '__main__':
    import sys
    sys.modules['moduleA'] = sys.modules['__main__']

import moduleB
Run Code Online (Sandbox Code Playgroud)

我不认为这是非常Pythonic.