python - 为什么在尝试将 Enum 用作另一个文件中的字典键时出现 KeyError?

标签 python

我有两个文件,enum_test.pyprint_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/

相关文章:

c++ - 将带有前置和后置增量运算符的 C++ 转换为 Python 时出现问题

python - Python 中的 Google Talk/XMPP 音频支持

python - 如何在 Hy 中构建 Python 模块?

php - 在沙盒模式下运行 PHP、Ruby 或 Python 进程

python - 如何在python3中刷新/清除套接字中的缓冲区

python - 从移动目录加载 tensorflow 模型

python - 重复时间序列数据的 Pandas 滚动中位数

python - 带有 Click 库的 Python 3.6 中没有模块错误

python - 如何使用plotly使 map 适合宽度(python)

python - 给定经纬度列表,如何在球体上绘制热图?