pycharm 切換 python3.9 報錯 ‘HTMLParser‘ object has no attribute ‘unescape‘ 解決

2020-10-29 15:00:17

有的bug,莫名其妙就好了…

python3.9 報錯 「AttributeError: 'HTMLParser' object has no attribute 'unescape'」 異常分析解決。

一、問題描述

安裝 python3.9 版本後,pycharm 中切換 python3.9 版本,建立虛擬環境報錯:"AttributeError: 'HTMLParser' object has no attribute 'unescape'"。

Executed command:
    C:\Users\程式設計師的一天\AppData\Local\Temp\tmp41_yhcxspycharm-management\setuptools-40.8.0\setup.py install

Error occurred:
    AttributeError: 'HTMLParser' object has no attribute 'unescape'

Command output:
Traceback (most recent call last):
  File "C:\Users\程式設計師的一天\AppData\Local\Temp\tmp0mv4mj35pycharm-management\setuptools-40.8.0\setup.py", line 11, in <module>
    import setuptools
  File "C:\Users\程式設計師的一天\AppData\Local\Temp\tmp0mv4mj35pycharm-management\setuptools-40.8.0\setuptools\__init__.py", line 20, in <module>
    from setuptools.dist import Distribution, Feature
  File "C:\Users\程式設計師的一天\AppData\Local\Temp\tmp0mv4mj35pycharm-management\setuptools-40.8.0\setuptools\dist.py", line 35, in <module>
    from setuptools.depends import Require
  File "C:\Users\程式設計師的一天\AppData\Local\Temp\tmp0mv4mj35pycharm-management\setuptools-40.8.0\setuptools\depends.py", line 7, in <module>
    from .py33compat import Bytecode
  File "C:\Users\程式設計師的一天\AppData\Local\Temp\tmp0mv4mj35pycharm-management\setuptools-40.8.0\setuptools\py33compat.py", line 55, in <module>
    unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape)
AttributeError: 'HTMLParser' object has no attribute 'unescape'

檢視官網 python3.9changelog,發現 HTMLParser.unescape 屬性被移除了,並且從 python3.4 開始就被棄用。

python3.9 changelog

pycharm 建立虛擬環境時,會使用到 setuptools。而 setuptools 中,剛好使用了這個屬性,所以,導致了"AttributeError: 'HTMLParser' object has no attribute 'unescape'"異常。

經過各種分析、嘗試,問題最終得到解決。記錄下過程,避免更多人踩坑。

二、解決方法

先給出解決方法,感興趣的朋友,可以繼續閱讀後面的分析部分。

解決這個問題,分兩種情況:

1. 不通過 pycharm 編輯器,直接使用 python 直譯器。
2. 在 pycharm 編輯器中使用 python 直譯器。

我是在 pycharm 中使用 python3.9 觸發報錯,所以這裡也單獨提出來討論討論。

2.1、直接使用 python 直譯器

不通過 pycharm 編輯器,直接使用 python 直譯器。比如,在 windowscmd ,或 linux 下的命令列中使用 python

解決方法:更新 setuptools 版本。
我以 python3.9 使用 setuptools 為例,測試如下。

2.1.1、setuptools 低版本觸發報錯

setuptools-40.8.0 為例,測試觸發報錯如下:

第一步,使用 python3.9 下的 pip 解除安裝之前安裝的 setuptools:

E:\soft\python\python39\install>pip uninstall setuptools

第二步,安裝 setuptools-40.8.0

E:\soft\python\python39\install>pip install setuptools==40.8.0
Collecting setuptools==40.8.0
  Using cached setuptools-40.8.0-py2.py3-none-any.whl (575 kB)
Installing collected packages: setuptools
Successfully installed setuptools-40.8.0

第三步,在 python3.9 中匯入包觸發報錯:

E:\soft\python\python39\install>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import setuptools
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "E:\soft\python\python39\install\lib\site-packages\setuptools\__init__.py", line 20, in <module>
    from setuptools.dist import Distribution, Feature
  File "E:\soft\python\python39\install\lib\site-packages\setuptools\dist.py", line 35, in <module>
    from setuptools.depends import Require
  File "E:\soft\python\python39\install\lib\site-packages\setuptools\depends.py", line 7, in <module>
    from .py33compat import Bytecode
  File "E:\soft\python\python39\install\lib\site-packages\setuptools\py33compat.py", line 55, in <module>
    unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape)
AttributeError: 'HTMLParser' object has no attribute 'unescape'
2.1.2、setuptools 高版本解決報錯

setuptools-49.2.1 為例,測試如下:

第一步,解除安裝之前安裝的 setuptools:

E:\soft\python\python39\install>pip uninstall setuptools
Found existing installation: setuptools 40.8.0
Uninstalling setuptools-40.8.0:
  Would remove:
    e:\soft\python\python39\install\lib\site-packages\easy_install.py
    e:\soft\python\python39\install\lib\site-packages\pkg_resources\*
    e:\soft\python\python39\install\lib\site-packages\setuptools-40.8.0.dist-info\*
    e:\soft\python\python39\install\lib\site-packages\setuptools\*
    e:\soft\python\python39\install\scripts\easy_install-3.9.exe
    e:\soft\python\python39\install\scripts\easy_install.exe
Proceed (y/n)? y
  Successfully uninstalled setuptools-40.8.0

第二步,安裝 setuptools==49.2.1:

E:\soft\python\python39\install>pip install setuptools==49.2.1
Collecting setuptools==49.2.1
  Using cached setuptools-49.2.1-py3-none-any.whl (789 kB)
Installing collected packages: setuptools
Successfully installed setuptools-49.2.1

第三步,在 python3.9 中匯入包:

E:\soft\python\python39\install>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import setuptools
>>> setuptools.__version__
'49.2.1'
>>>

目前最新版本,應該是到 setuptools-50.3.2 了 。


2.2、在 pycharm 中使用 python 直譯器

pycharm 中建立 python3.9 虛擬環境報錯,本質上也是使用了 setuptools 的低版本導致。
我嘗試過更新 setuptools 為更高的版本,但 pycharm 還是頑固的使用了 setuptools-40.8.0,如最開始的報錯資訊所示…

我不知道是 pycharm 中的某些預設設定導致,還是 pycharm 的版本屬性導致它使用了低版本的 setuptools,如果有朋友知道,歡迎告知。

雖然,不知道 pycharm 中選擇低版本 setuptools 的原因。這裡,也簡單提供兩種解決方法吧~

2.2.1、virtualenv 建立虛擬環境

virtualenv 為應用提供隔離的 Python 執行環境,可以解決不同應用間多版本 python 的衝突問題。

利用 virtualenv 建立虛擬環境後,pycharm 中建立虛擬環境時,選擇已存在的虛擬環境,可以避開報錯。

第一步: 確認 python3.9 對應的 pip 工具。
如果沒有配環境變數,可以直接從安裝路徑下開啟 cmd 工具。一般在 python 安裝目錄下的 Scripts 資料夾內。使用 pip -V 可以檢視 pip 對應的 python 版本。

E:\soft\python\python39\install>pip -V
pip 20.2.4 from e:\soft\python\python39\install\lib\site-packages\pip (python 3.9)

第二步: 安裝 virtualenv

pip install virtualenv

第三步: 建立虛擬環境。
virtualenv 指令用於建立虛擬環境,後跟虛擬環境儲存路徑。

virtualenv E:\soft\python\python39\env

如果需要刪除虛擬環境,直接刪除對應資料夾即可。

第四步: pycharm 中選擇已存在的虛擬環境。
"File --> Settings --> Python Interpreter",進入對應介面。

pycharm中選擇已存在虛擬環境

這裡,需要選擇到虛擬環境中的 python.exe,否則 OK 鍵為灰色,無法點選。

通過該方法,可以在原本報錯的 pycharm 中建立 python3.9 虛擬環境。

2.2.2、pycharm 版本更換

報錯版本為:pycharm-community-2019.2.1
下載安裝最新版本:pycharm-community-2020.2.3

點選執行要安裝的 pycharm-community-2020.2.3.exe 檔案,會自動檢測,提示解除安裝已安裝的pycharm

為避免其他問題,解除安裝過程中,可以選擇刪除舊版本設定等。

解除安裝過程中選擇刪除快取配置和已安裝插件等

經過測試,使用最新版本 pycharm 可以成功建立 python3.9 虛擬環境。
為了驗證是否為 pycharm 的版本相容問題,我解除安裝最新版本,重新安裝舊版本 pycharm 後,依然報錯!我猜測是固定的 pycharm 版本,使用了固定的某些 setuptools 版本,導致了相容性報錯。

我也懷疑過是系統中多個版本 python 的環境變數順序,導致pycharm 找到了錯誤的依賴項。嘗試在環境變數中將 python3.9 相關值移動到最前面,依然不能解決問題。

看來,最新的 python 還是得配最新的 pycharm編碼界的愛情故事麼…

三、原因分析

感興趣的朋友,歡迎繼續閱讀。

Traceback 報錯紀錄檔中,可以看到,是在 setuptools-40.8.0\setuptools\py33compat.py 的55行, 執行 unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape) 時,丟擲了 AttributeError: 'HTMLParser' object has no attribute 'unescape' 異常。

可以肯定是由 setuptools 引起的報錯。這裡有一個關鍵的資訊:py33compat.py 檔案。
pyXXcompat.pysetuptools 相容 python 版本相關的檔案。

進入到 ..\Lib\site-packages\setuptools 檢視 setuptools-40.8.0 的安裝檔案,可以看到,包含了 py27compat.pypy31compat.pypy33compat.py

setuptools-40.8.0相容檔案

進入到 ..\Lib\site-packages\setuptools 檢視 setuptools-49.2.1 的安裝檔案,可以看到,只包含了 py34compat.py

setuptools-49.2.1相容檔案

而我們從 python3.9changelog 中,可以知道 HTMLParser.unescape 屬性被移除了,並且從 python3.4 開始就被棄用了。

所以,從相容 python3.4 開始,setuptools 中就放棄了使用 HTMLParser.unescape
因此,只要包含 py34compat.py 檔案的 setuptools 版本,就能相容 python3.9 版本。

END.

原創不易,點個讚唄!如果喜歡,可以打賞請作者喝奶茶喲:)

工作之餘,喜歡寫些東西,記錄生活、總結技術。感興趣的微信朋友,可以搜一搜:【程式設計師的一天】,歡迎關注、支援,謝謝!