我有两个文件,enum_test.py
和 print_test_file.py
.我在 enum_test.py
中定义了一个 Enum 类并使用该 Enum 类的成员作为键创建了一个字典。当我试图在 print_test_file.py
中使用该词典时我遇到了一个关键错误。
这是 enum_test.py
的代码:
from enum import Enum
import print_test_file
class MyEnum(Enum):
A = 1
B = 2
def main():
enumDict = dict()
enumDict[MyEnum.A] = 'abcd'
enumDict[MyEnum.B] = 'efgh'
print(enumDict[MyEnum.A])
print_test_file.print_test(enumDict)
if __name__ == "__main__":
main()
这是来自 print_test_file.py
的代码
import enum_test
def print_test(enumDict):
print(enumDict[enum_test.MyEnum.A])
我期待运行 enum_test
将产生以下输出:
abcd
abcd
但它只打印第一个 abcd
然后抛出 KeyError: <MyEnum.A: 1>
如何使用我在 enum_test.py
中创建的词典来自 print_test_file.py
?
最佳答案
这就是为什么你不应该导入
你作为脚本运行的相同模块。您最终会得到两个完全独立的模块对象,enum_test
和 __main__
,它们具有自己完全独立的全局命名空间,包含由相同代码构造的独立对象。
__main__.main()
构建一个字典,并用 __main__.MyEnum
键填充它。
print_test_file.print_test
将该字典作为参数。但随后它尝试使用 enum_test.MyEnum.A
搜索它。那个字典中不存在那个键。所以你得到一个KeyError
。
你的模块也有循环依赖,这个问题掩盖了这一点。我很确定如果没有其他问题的话,在这种情况下你实际上可以摆脱循环依赖,但是必须仔细考虑顶级模块代码的执行顺序仍然令人困惑,所以最好避免他们。
同时解决这两个问题的简单方法是将共享代码移动到一个单独的共享模块中,您的脚本和测试模块都可以导入该模块。
# enum_test.py
from my_enum import MyEnum
import print_test_file
def main():
enumDict = dict()
enumDict[MyEnum.A] = 'abcd'
enumDict[MyEnum.B] = 'efgh'
print(enumDict[MyEnum.A])
print_test_file.print_test(enumDict)
if __name__ == "__main__":
main()
# print_test_file.py
import my_enum
def print_test(enumDict):
print(enumDict[my_enum.MyEnum.A])
# my_enum.py
from enum import Enum
class MyEnum(Enum):
A = 1
B = 2
现在,没有导入脚本的模块,也没有导入脚本的模块。 (在技术术语中,您只有一棵树,脚本位于根部,而不是其中包含循环的图形。)
每隔几年,有人建议更换 Python 来消除这个问题,但确实没有好的答案。他们可能会错误地导入作为脚本运行的同一模块,但这可能会破坏一些不常见但重要的用例(如 multiprocessing
)。或者他们可以通过在某处执行隐式 sys.modules['enum_test'] = sys.modules['__main__']
使其“正常工作”——但实际上没有“某处”可以不要将代码中的循环依赖(以及此问题的几乎所有其他示例)从几乎无害变成严重错误。
(顺便说一下,我依稀记得在一次讨论中,一位核心开发人员同时也是一名教师提到他的学生中很少有人遇到过这个问题,但遇到的人往往都接近类的佼佼者,所以至少你可以感觉良好。)
关于python - 为什么在尝试将 Enum 用作另一个文件中的字典键时出现 KeyError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51509644/