Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Enums across Modules

Why can in Python 3 enum equality not be checked correctly across module boundaries if the enum has been defined in the main module? Here is an example:

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)

moduleB.py:

#!/usr/bin/python3

import moduleA

def doStuff(aVariable):
    bVariable = moduleA.MyEnum.B
    assert aVariable == bVariable

Calling "./moduleA.py" on the command line yields:

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

Uncommenting the custom equality operator in the enum leads to an assertion failure there. I've found that the class module is not the same in both cases, as it is "__main__" in one case.

What is the most "Pythonic way" to fix this problem (other than moving the enum to its own module)?

EDIT: Switching to "aVariable is bVariable" does not work either:

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
like image 538
DCTLib Avatar asked Oct 27 '14 14:10

DCTLib


People also ask

How to use enums in Python?

Enums can be displayed as string or repr. 2. Enums can be checked for their types using type (). 3. “ name ” keyword is used to display the name of the enum member. 4. Enumerations are iterable. They can be iterated using loops

What is an enum in C++?

An enumeration is a set of members that have associated unique constant values. Create a new enumeration by defining a class that inherits from the Enum type of the enum module. The members have the same types as the enumeration to which they belong.

What is enumeration in Python?

Summary: in this tutorial, you’ll learn about Python enumeration and how to use it effectively. By definition, an enumeration is a set of members that have associated unique constant values. Enumeration is often called enum. Python provides you with the enum module that contains the Enum type for defining new enumerations.

What happened to enum class member changed in Python?

Changed in version 3.11. Enum members are instances of their enum class, and are normally accessed as EnumClass.member. In Python versions 3.5 to 3.10 you could access members from other members – this practice was discouraged, and in 3.11 Enum returns to not allowing it:


1 Answers

As far as Python is concerned, you have three modules here:

  • __main__
  • moduleA
  • moduleB

The file you run from the command line, the main entry point, is always stored as the __main__ module. If you import moduleA anywhere in the code, Python sees that as separate from the __main__ module and creates instead a new module object. You thus have two separate MyEnum classes:

  • __main__.MyEnum
  • moduleA.MyEnum

Their members are distinct and thus cannot be equal.

Your test passes if instead of using import moduleA you used import __main__ as moduleA, or used a separate script file to drive the test; that separate file would become __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)

Another workaround would be to tell Python that __main__ and moduleA are the same thing; before importing moduleA (or moduleB, which imports moduleA) you can add another entry to sys.modules:

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

import moduleB

I'd not consider this very Pythonic.

like image 123
Martijn Pieters Avatar answered Sep 23 '22 06:09

Martijn Pieters