关于python:从脚本导入已安装的软件包引发“AttributeError:module has no attribute”或“ImportError:无法导入名称”

Importing installed package from script raises “AttributeError: module has no attribute” or “ImportError: cannot import name”

我有一个名为requests.py的脚本,用于导入请求包。脚本无法访问包中的属性,或者无法导入这些属性。为什么这个不起作用,我该怎么修复它?

以下代码引发一个AttributeError

1
2
3
4
import requests

res = requests.get('http://www.google.ca')
print(res)
1
2
3
4
5
6
Traceback (most recent call last):
  File"/Users/me/dev/rough/requests.py", line 1, in <module>
    import requests
  File"/Users/me/dev/rough/requests.py", line 3, in <module>
    requests.get('http://www.google.ca')
AttributeError: module 'requests' has no attribute 'get'

下面的代码引发一个ImportError

1
2
3
4
from requests import get

res = get('http://www.google.ca')
print(res)
1
2
3
4
5
6
Traceback (most recent call last):
  File"requests.py", line 1, in <module>
    from requests import get
  File"/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests import get
ImportError: cannot import name 'get'

或从requests包内的模块导入的代码:

1
from requests.auth import AuthBase
1
2
3
4
5
6
Traceback (most recent call last):
  File"requests.py", line 1, in <module>
    from requests.auth import AuthBase
  File"/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests.auth import AuthBase
ImportError: No module named 'requests.auth'; 'requests' is not a package


这是因为名为requests.py的本地模块隐藏了您试图使用的已安装requests模块。当前目录是在sys.path前面,因此本地名称优先于已安装的名称。

当出现这种情况时,一个额外的调试提示是仔细查看回溯,并意识到所讨论的脚本的名称与您试图导入的模块相匹配:

注意脚本中使用的名称:

1
File"/Users/me/dev/rough/requests.py", line 1, in <module>

您要导入的模块:requests

将模块重命名为其他名称以避免名称冲突。

python可以在你的requests.py文件旁边(在python 3的__pycache__目录中)生成一个requests.pyc文件。在重命名之后也要删除它,因为解释器仍将引用该文件,从而重新产生错误。但是,如果删除了py文件,__pycache__中的pyc文件不应影响代码。

在本例中,将文件重命名为my_requests.py,删除requests.pyc,然后再次运行,即可成功打印


对于原始问题的编写者,以及那些搜索"attributeError:module has no attribute"字符串的人,根据接受的答案,常见的解释是,用户创建的脚本的名称与库文件名冲突。但是,请注意,问题可能不在生成错误的脚本的名称中(与上面的情况一样),也不在该脚本显式导入的库模块的任何名称中。可能需要做一些侦查工作来找出是哪个文件导致了这个问题。

举个例子来说明这个问题,假设您正在创建一个脚本,它使用"decimal"库使用十进制数字进行精确的浮点计算,并将脚本命名为"EDOCX1"(13),其中包含行"EDOCX1"(14)。这些都没有问题,但您会发现它引发了这个错误:

1
AttributeError: 'module' object has no attribute 'Number'

如果您以前编写了一个名为"numbers.py的脚本,就会发生这种情况,因为"decimal"库调用标准库的"numbers",但会找到旧的脚本。即使您删除了它,也可能无法解决问题,因为Python可能已经将其转换为字节码,并将其存储在缓存中,称为"EDOCX1"(16),所以您也必须找到它。