从同名脚本导入已安装的包会引发"AttributeError:module has no attribute ",ImportError或NameError。

14 浏览
0 Comments

从同名脚本导入已安装的包会引发"AttributeError:module has no attribute ",ImportError或NameError。

我有一个命名为 requests.py 的脚本需要使用第三方的 requests 包。但是脚本要么无法导入这个包,要么无法访问它的功能。

为什么会出现这种情况,应该怎么解决?

使用普通的导入方式,然后使用功能会导致一个 AttributeError 错误:

import requests
res = requests.get('http://www.google.ca')
print(res)

Traceback (most recent call last):
  File "/Users/me/dev/rough/requests.py", line 1, in 
    import requests
  File "/Users/me/dev/rough/requests.py", line 3, in 
    requests.get('http://www.google.ca')
AttributeError: module 'requests' has no attribute 'get'

在更近版本的 Python 中,错误消息会变成 AttributeError: 部分初始化模块 \'requests\' 没有 \'get\' 属性(最可能是由于循环导入)

使用从导入方式导入一个具体的名称会导致 ImportError 错误:

from requests import get
res = get('http://www.google.ca')
print(res)

Traceback (most recent call last):
  File "requests.py", line 1, in 
    from requests import get
  File "/Users/me/dev/rough/requests.py", line 1, in 
    from requests import get
ImportError: cannot import name 'get'

在更近版本的 Python 中,错误消息会变成 ImportError: 无法从部分初始化的模块 \'requests\' 中导入名称 \'get\'(最可能是由于循环导入)(/ Users / me / dev / rough / requests.py)

在包中使用从导入方式导入一个模块会导致不同的 ImportError 错误:

from requests.auth import AuthBase

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

使用星号导入方式,然后使用功能会触发一个 NameError 错误:

from requests import *
res = get('http://www.google.ca')
print(res)

Traceback (most recent call last):
  File "requests.py", line 1, in 
    from requests import *
  File "/Users/me/dev/rough/requests.py", line 3, in 
    res = get('http://www.google.ca')
NameError: name 'get' is not defined

admin 更改状态以发布 2023年5月21日
0
0 Comments

错误的原因是用户创建的脚本与库文件名冲突。但需要注意的是,这个问题可能是间接造成的。需要一些侦探工作才能找出是哪个文件引起了问题。\n\n例如:假设你有一个名为mydecimal.py的脚本,其中包括import decimal,目的是使用标准库的decimal库进行带小数位数值的准确浮点计算。这样不会引起问题,因为不存在标准库的mydecimal。但是,decimal导入了numbers(另一个标准库模块)用于内部使用,因此你的项目中的名为numbers.py的脚本会引起问题。\n\n在一个特别棘手的案例中,项目中有一个名为token.py的文件(或在Python交互模式下启动时的当前工作目录),会导致交互式帮助无法正常显示:\n\n

$ touch token.py
$ python
Python 3.8.10 (default, Nov 14 2022, 12:59:47) 
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> help
Type help() for interactive help, or help(object) for help about object.
>>> help()
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.8/_sitebuiltins.py", line 102, in __call__
    import pydoc
  File "/usr/lib/python3.8/pydoc.py", line 66, in 
    import inspect
  File "/usr/lib/python3.8/inspect.py", line 40, in 
    import linecache
  File "/usr/lib/python3.8/linecache.py", line 11, in 
    import tokenize
  File "/usr/lib/python3.8/tokenize.py", line 35, in 
    from token import EXACT_TOKEN_TYPES
ImportError: cannot import name 'EXACT_TOKEN_TYPES' from 'token' (/current/working/directory/token.py)

\n\n回溯告诉我们所有需要知道的信息:调用help会触发延迟导入标准库pydoc,该文件间接尝试导入标准库token,但发现我们的token.py并不包含适当的名称。在旧版本的Python中,情况甚至更糟: tokenize会从token进行星号导入,然后它的顶层代码会尝试在那里定义的名称,导致NameError和堆栈跟踪没有提到token.py。\n\n如果在项目中跟踪并重命名或删除适当的.py文件后仍然遇到此类问题,则还要检查Python在导入模块时用于缓存字节码编译的.pyc文件。在 3.x 中,这些文件将存储在具有特殊名称__pycache__的文件夹中;可以安全地删除这些文件夹和文件,也可以抑制它们(但通常不希望这样做)。

0
0 Comments

这是因为你的本地模块命名为requests.py,遮盖了你尝试使用的已安装的requests模块。当前目录将作为sys.path前缀,因此本地名称优先于已安装的名称。

当出现这种情况时,一个额外的调试提示是仔细查看Traceback,并意识到你的脚本名称与你尝试导入的模块名称匹配:

注意你在脚本中使用的名称:

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

你尝试导入的模块:requests

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

Python可能会在你的requests.py文件旁边生成一个requests.pyc文件(在Python 3的__pycache__目录中)。重命名之后还应该把它删除,因为解释器仍然会引用该文件,从而重新产生错误。但是__pycache__中的pyc文件如果已经被删除,则不会影响你的代码。

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


注意:当你将文件命名为你要导入的模块时,这不仅会发生。如果你将文件命名为直接导入模块所导入的模块的名称,则也可能发生这种情况。例如,有一个名为copy.py的文件,并试图从那里import pandas,将会出现

ImportError: cannot import name 'copy' from 'copy'

这是因为pandas导入了copy。这里没有神奇的解决方案,因为你不能知道世界上所有模块的名称,但有一个经验法则是尽可能使模块名称唯一,并在出现此类错误时尝试更改名称。

0