Python3.6.报错“module‘enum‘hasnoattribute‘IntFlag‘”的真正原因与解决办法

作者:

文章目录
  • 有一天你刚刚装好 Python 3.6.1,信心满满地敲下命令: python3 结果刚刚打开控制台,终端就给了你一个当头一棒: AttributeError: module 'enum' has no attribute 'IntFlag' 看起来好像是 Python 内部的 bug,对吧? 其实并不是。这个问题的根本原因非常“隐蔽”——是你项目(或系统路径)中存在一个名为 enum.py 的文件,覆盖了标准库的 enum 模块。 下面我们一起来还原这个坑的全过程。
  • 首先,这个问题常出现在以下环境中: macOS 系统; Python 版本 3.6.1(但也可能在 3.7 甚至 3.8 出现); 安装路径类似 /Library/Frameworks/Python.framework/…; 启动解释器或运行任何 Python 文件时,报如下错误: AttributeError: module 'enum' has no attribute 'IntFlag' 你可能第一反应是: “明明 Python 3.6 已经支持 IntFlag 啊,这不应该报错啊?” 是的,Python 3.6.1 的 enum 模块确实定义了 IntFlag 类: # Python 3.6 源码 enum.py 中的一部分 class IntFlag(Flag): pass 那为什么解释器还会报 “enum 没有 IntFlag” 呢?别急,下面揭开谜底。
  • Python 的导入机制其实非常简单——它会按照 sys.path 的顺序依次搜索模块。 一旦它在某个路径下找到了名为 enum.py 的文件,它就会优先导入那个文件,而不是标准库自带的。 比如,你的项目结构是这样的: /Users/yourname/project/├── enum.py├── main.py 你在 main.py 里执行了: import enum Python 实际上导入的是你项目目录下的 enum.py,而不是标准库的 enum 模块。于是,这个自定义的 enum.py 文件里没有 IntFlag 类,解释器自然就抛出了: AttributeError: module 'enum' has no attribute 'IntFlag' 本质上是:你“遮蔽”了标准库模块。
  • 我们自己来做个小实验,看它是怎么被“遮蔽”的: # enum.py (放在当前目录) print(“自定义 enum 模块被导入”) def dummy(): pass 然后运行一个测试文件: # main.py import enum print(enum) print(dir(enum)) 执行结果: 自定义 enum 模块被导入<module 'enum' from '/Users/yourname/project/enum.py'>['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 'dummy'] 可以看到,Python 确实导入了我们自己定义的 enum.py。所以,系统的 enum.IntFlag 根本没有机会被加载。
  • 这个问题的修复其实非常简单,通常有三种做法:
  • 我们来做个对比实验,验证修复后的正确行为。
  • 这种“本地文件覆盖标准库”的问题非常常见。 开发者最常踩的几个坑还有: 模块名 常见误伤 结果 enum.py 覆盖标准库 enum AttributeError: no attribute random.py 覆盖 random 模块 AttributeError: module ‘random’ has no attribute ‘randint’ json.py 覆盖 json 模块 TypeError: ‘str’ object is not callable asyncio.py 覆盖 asyncio 框架 ImportError: cannot import name ‘Future’ logging.py 覆盖 logging 模块 AttributeError: module ‘logging’ has no attribute ‘getLogger’ 总结一句:永远不要用标准库同名文件命名你的模块。
  • 这次的 AttributeError: module 'enum' has no attribute 'IntFlag',并不是 Python 本身的 bug,而是开发环境中“命名冲突”引起的导入遮蔽。 核心要点: Python 导入模块时会优先搜索当前目录; 如果当前目录下存在同名文件,会覆盖标准库模块; 删除或重命名冲突文件即可恢复正常。 一句话总结: 不是 Python 坏了,是你的文件名太像标准库了。
  • 建议你在项目初始化时养成习惯: 使用 flake8 或 pylint 检查模块命名; 配合 venv 或 conda 建立独立虚拟环境; 不要直接在系统目录下运行自定义模块。 这样不仅能避免这类问题,还能让环境更干净,避免未来升级或迁移时出问题。 到此这篇关于Python 3.6.报错 “module ‘enum‘ has no attribute ‘IntFlag‘”的真正原因与解决办法的文章就介绍到这了,更多相关Python module enum has no attribute IntFlag问题内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法 Python2到Python3的迁移过程中报错AttributeError: ‘str‘ object has no attribute ‘decode‘问题的解决方案大全 解决python报错:AttributeError: 'ImageDraw' object has no attribute 'textbbox' Python 中 AttributeError: ‘NoneType‘ object has no attribute ‘X‘ 错误问题解决方案 Python进程崩溃AttributeError异常问题解决 解决python多线程报错:AttributeError: Can”t pickle local object问题 Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决 python错误:AttributeError: ”module” object has no attribute ”setdefaultencoding”问题的解决方法
  • 目录
    • 摘要
    • 背景与问题重现
    • 问题原因分析
    • 实战验证:如何复现这个错误
    • 正确的解决方案
      • 方案一:删除或重命名本地的enum.py
      • 方案二:检查__pycache__目录
      • 方案三:检查 sys.path 顺序
    • 可运行 Demo:验证修复前后效果
      • 修复前
      • 修复后(删除 enum.py)
    • 延伸思考:这个坑不只发生在 enum
      • 总结
        • 小贴士

          有一天你刚刚装好 Python 3.6.1,信心满满地敲下命令:

          python3
          

          结果刚刚打开控制台,终端就给了你一个当头一棒:

          AttributeError: module 'enum' has no attribute 'IntFlag'

          看起来好像是 Python 内部的 bug,对吧?

          其实并不是。这个问题的根本原因非常“隐蔽”——是你项目(或系统路径)中存在一个名为 enum.py 的文件,覆盖了标准库的 enum 模块

          下面我们一起来还原这个坑的全过程。

          首先,这个问题常出现在以下环境中:

          macOS 系统;

          Python 版本 3.6.1(但也可能在 3.7 甚至 3.8 出现);

          安装路径类似 /Library/Frameworks/Python.framework/...

          启动解释器或运行任何 Python 文件时,报如下错误:

          AttributeError: module 'enum' has no attribute 'IntFlag'

          你可能第一反应是:

          “明明 Python 3.6 已经支持 IntFlag 啊,这不应该报错啊?”

          是的,Python 3.6.1 的 enum 模块确实定义了 IntFlag 类:

          # Python 3.6 源码 enum.py 中的一部分
          class IntFlag(Flag):
              pass
          

          那为什么解释器还会报 “enum 没有 IntFlag” 呢?别急,下面揭开谜底。

          Python 的导入机制其实非常简单——它会按照 sys.path 的顺序依次搜索模块。

          一旦它在某个路径下找到了名为 enum.py 的文件,它就会优先导入那个文件,而不是标准库自带的。

          比如,你的项目结构是这样的:

          /Users/yourname/project/
          ├── enum.py
          ├── main.py

          你在 main.py 里执行了:

          import enum
          

          Python 实际上导入的是你项目目录下的 enum.py,而不是标准库的 enum 模块。于是,这个自定义的 enum.py 文件里没有 IntFlag 类,解释器自然就抛出了:

          AttributeError: module 'enum' has no attribute 'IntFlag'

          本质上是:你“遮蔽”了标准库模块。

          我们自己来做个小实验,看它是怎么被“遮蔽”的:

          # enum.py (放在当前目录)
          print("自定义 enum 模块被导入")
          
          def dummy():
              pass
          

          然后运行一个测试文件:

          # main.py
          import enum
          
          print(enum)
          print(dir(enum))
          

          执行结果:

          自定义 enum 模块被导入
          <module 'enum' from '/Users/yourname/project/enum.py'>
          ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 'dummy']

          可以看到,Python 确实导入了我们自己定义的 enum.py。所以,系统的 enum.IntFlag 根本没有机会被加载。

          这个问题的修复其实非常简单,通常有三种做法:

          最直接有效的方法就是:

          • 找到你项目或用户目录下的 enum.py
          • 删除它;
          • 或者改个名,比如 my_enum.py

          然后重新运行程序,就一切正常了。

          即使你已经删除了 enum.py,有时候 Python 还会加载缓存文件。

          所以建议同时清理掉:

          __pycache__/enum.cpython-36.pyc
          

          否则缓存模块仍可能被误导入。

          如果你在多项目环境下开发,可以打印当前解释器的模块搜索路径:

          import sys
          for p in sys.path:
              print(p)
          

          一般情况下,当前工作目录会排在最前面:

          /Users/yourname/project
          /usr/local/lib/python3.6

          你也可以临时调整 sys.path 的顺序(不推荐长期使用):

          import sys
          sys.path.remove('/Users/yourname/project')
          

          我们来做个对比实验,验证修复后的正确行为。

          $ python3
          >>> import enum
          >>> enum.IntFlag
          Traceback (most recent call last):
            ...
          AttributeError: module 'enum' has no attribute 'IntFlag'
          

          $ python3
          >>> import enum
          >>> enum.IntFlag
          <enum 'IntFlag'>
          

          问题成功解决

          这种“本地文件覆盖标准库”的问题非常常见。

          开发者最常踩的几个坑还有:

          模块名 常见误伤 结果
          enum.py 覆盖标准库 enum AttributeError: no attribute
          random.py 覆盖 random 模块 AttributeError: module ‘random’ has no attribute ‘randint’
          json.py 覆盖 json 模块 TypeError: ‘str’ object is not callable
          asyncio.py 覆盖 asyncio 框架 ImportError: cannot import name ‘Future’
          logging.py 覆盖 logging 模块 AttributeError: module ‘logging’ has no attribute ‘getLogger’

          总结一句:永远不要用标准库同名文件命名你的模块。

          这次的 AttributeError: module 'enum' has no attribute 'IntFlag',并不是 Python 本身的 bug,而是开发环境中“命名冲突”引起的导入遮蔽。

          核心要点:

          • Python 导入模块时会优先搜索当前目录;
          • 如果当前目录下存在同名文件,会覆盖标准库模块;
          • 删除或重命名冲突文件即可恢复正常。

          一句话总结:

          不是 Python 坏了,是你的文件名太像标准库了。

          建议你在项目初始化时养成习惯:

          • 使用 flake8pylint 检查模块命名;
          • 配合 venvconda 建立独立虚拟环境;
          • 不要直接在系统目录下运行自定义模块。

          这样不仅能避免这类问题,还能让环境更干净,避免未来升级或迁移时出问题。

          到此这篇关于Python 3.6.报错 “module ‘enum‘ has no attribute ‘IntFlag‘”的真正原因与解决办法的文章就介绍到这了,更多相关Python module enum has no attribute IntFlag问题内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法
          • Python2到Python3的迁移过程中报错AttributeError: ‘str‘ object has no attribute ‘decode‘问题的解决方案大全
          • 解决python报错:AttributeError: 'ImageDraw' object has no attribute 'textbbox'
          • Python 中 AttributeError: ‘NoneType‘ object has no attribute ‘X‘ 错误问题解决方案
          • Python进程崩溃AttributeError异常问题解决
          • 解决python多线程报错:AttributeError: Can”t pickle local object问题
          • Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决
          • python错误:AttributeError: ”module” object has no attribute ”setdefaultencoding”问题的解决方法

          站内搜索