TencentCloud / tencentcloud-cli

Tencent Cloud API 3.0 Command Line Interface
Apache License 2.0
90 stars 26 forks source link

属性错误:type object 'Callable' has no attribute '_abc_registry' #42

Closed China-ms closed 2 years ago

China-ms commented 2 years ago

在提此问题之前,首先感谢官方工作人员的耐心对接,及时进行了验证,开展了良好的沟通。现将问题描述如下:

OS:

Python版本:

tccli版本:

描述:

上次使用tccli是半年前,未发现问题,本次因测试THPC的需要更新了tccli,结果敲第一个命令就报错:

> tccli thpc help
usage: tccli [options] <command> <subcommand> [<subcommand> ...] [parameters]
To tccli help text, you can run:

  tccli help
  tccli configure help
  tccli service[cvm] help
  tccli service[cvm] action[RunInstances] help

type object 'Callable' has no attribute '_abc_registry'

当意识到这是报错时(Error提示也不太明显),基本就判断是因为环境问题,因为命令很基础且错误不常见。 通过简单修改源码并打印异常栈后发现,是导入requests时,其charset_normalizer包使用了typing类型提示:

  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/tencentcloud/common/abstract_client.py", line 37, in <module>
    from tencentcloud.common.http.request import ApiRequest
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/tencentcloud/common/http/request.py", line 7, in <module>
    import requests
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/requests/__init__.py", line 48, in <module>
    from charset_normalizer import __version__ as charset_normalizer_version
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/charset_normalizer/__init__.py", line 24, in <module>
    from .api import from_bytes, from_fp, from_path, normalize
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/charset_normalizer/api.py", line 3, in <module>
    from typing import BinaryIO, List, Optional, Set
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/typing.py", line 1359, in <module>
    class Callable(extra=collections_abc.Callable, metaclass=CallableMeta):
  File "/home/sagene/software/miniconda3/lib/python3.8/site-packages/typing.py", line 1007, in __new__
    self._abc_registry = extra._abc_registry
AttributeError: type object 'Callable' has no attribute '_abc_registry'

可以看到这里的typing.py是一个第三方库,通过查看PyPI可以知道typing在3.5及以后已经内置,无需再使用该第三方库。(NOTE: in Python 3.5 and later, the typing module lives in the stdlib, and installing this package has NO EFFECT, because stdlib takes higher precedence than the installation directory.) 于是采取措施运行pip uninstall typing卸载该库后,再次运行上述help命令,成功看到输出。

原因:

为什么会出现这种错误?最直接的原因是环境中意外安装了不需要的包typing,然而联想到requests的使用是如此频繁,不仅自己经常使用,也有很多第三方库将其直接引入,为什么未出现本次报错的情况? 于是大概查看下源码,看到main.py的前几行时就茅塞顿开,原来是内部更改了sys.path的扫描路径,导致先读取的第三方typing包,忽略了内置的typing

base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, base)

这便是此次意外报错的深层次原因。 另外从根本上讨论,为什么3.7及之后的Python能复现该问题,3.6却不会报错,又为什么“”缺失“”了属性_abc_registry,其实都跟python抽象基类模块的代码实现有关。由于TCCLI努力兼容Python2.7及以上版本,所以这算是个隐藏的问题,偶尔可能会有人遇到,希望看到这里的人已经消除了疑惑。最后,关于内部修改扫描路径,应该是有其原因的,如果能有人分享下,那整个问题的清楚脉络就跃然眼前了。

解决:

zqfan commented 2 years ago

感谢。我们立刻着手修复,增加更高python版本测试环境

China-ms commented 2 years ago

感谢。我们立刻着手修复,增加更高python版本测试环境

好的不客气,辛苦了。