为什么我在尝试将枚举用作另一个文件中的字典键时遇到KeyError?

2024-06-12 06:48:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个文件,enum_test.pyprint_test_file.py。我在enum_test.py中定义了一个枚举类,并使用该枚举类的成员作为键创建了一个字典。当我试图在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的代码

^{pr2}$

我原以为运行enum_test会产生以下输出:

abcd
abcd

但是它只打印第一个abcd,然后抛出KeyError: <MyEnum.A: 1>

如何使用我在enum_test.py中从print_test_file.py创建的词典?在


Tags: 文件代码pytestimport字典定义main
1条回答
网友
1楼 · 发布于 2024-06-12 06:48:29

这正是为什么不应该import作为脚本运行的同一个模块。最后得到两个完全独立的模块对象,enum_test和{},它们有自己完全独立的全局命名空间,包含由同一代码构造的独立对象。在

__main__.main()生成dict,并用__main__.MyEnum键填充它。在

print_test_file.print_test将该dict作为参数。但是它会尝试使用enum_test.MyEnum.A来搜索它。而那个键不存在于那个dict中,所以得到一个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()

^{pr2}$
# my_enum.py
from enum import Enum

class MyEnum(Enum):
    A = 1
    B = 2

现在,没有模块可以导入脚本,也没有模块可以导入导入脚本的模块。(在技术术语中,与图中的循环不同,您只需要一个树,脚本位于根目录中。)


每隔几年,就有人建议更改Python来消除这个问题,但确实没有好的答案。它们可能会使导入作为脚本运行的同一个模块成为一个错误,但这可能会破坏一些不常见但重要的用例(如multiprocessing)。或者他们可以通过在某个地方隐式地执行sys.modules['enum_test'] = sys.modules['__main__']来使它“正常工作”,但实际上没有“某处”不会将代码中的循环依赖(以及几乎所有其他的这个问题的示例)从基本无害变为严重的bug。在

(顺便说一句,我模模糊糊地记得,在一次讨论中,一位同时也是老师的核心开发人员提到,他的学生中很少有人遇到过这个问题,但那些确实遇到过这种问题的学生往往会在班上名列前茅,所以至少你对此感到满意。)

相关问题 更多 >