今天在一台服务器上用 pip install 安装一个 package 时,没有安装成功,出现了“AttributeError: ‘tuple’ object has no attribute ‘read’”问题,后来发现 pip 所有功能都用不了了,list、uninstall 通通不行。老王在网上搜了搜,这个错误提示倒是挺多的,但因为 pip 引起的却没有,这里分享下问题原因和解决办法。
一、问题描述
系统版本:CentOS Linux release 7.6.1810
Python 版本:Python 3.6.9
pip 版本:pip 18.1
出现的具体原因就是在使用 pip 的任何功能时,例如 pip install/list/uninstall,都无法成功,报错信息如下:
Exception:
Traceback (most recent call last):
File “/usr/local/lib/python3.5/dist-packages/pip/_internal/basecommand.py”, line 228, in main
status = self.run(options, args)
File “/usr/local/lib/python3.5/dist-packages/pip/_internal/commands/uninstall.py”, line 46, in run
with self._build_session(options) as session:
File “/usr/local/lib/python3.5/dist-packages/pip/_internal/basecommand.py”, line 81, in _build_session
insecure_hosts=options.trusted_hosts,
File “/usr/local/lib/python3.5/dist-packages/pip/_internal/download.py”, line 338, in __init__
self.headers[“User-Agent”] = user_agent()
File “/usr/local/lib/python3.5/dist-packages/pip/_internal/download.py”, line 101, in user_agent
zip([“name”, “version”, “id”], distro.linux_distribution()),
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 120, in linux_distribution
return _distro.linux_distribution(full_distribution_name)
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 634, in linux_distribution
self.version(),
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 688, in version
self.lsb_release_attr(‘release’),
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 836, in lsb_release_attr
return self._lsb_release_info.get(attribute, ”)
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 522, in __get__
ret = obj.__dict__[self._fname] = self._f(obj)
File “/usr/local/lib/python3.5/dist-packages/pip/_vendor/distro.py”, line 933, in _lsb_release_info
stdout = subprocess.check_output(cmd, stderr=devnull)
File “/usr/lib/python3.5/subprocess.py”, line 626, in check_output
**kwargs).stdout
File “/usr/local/lib/python3.5/dist-packages/run/__init__.py”, line 145, in __new__
process = cls.create_process(command, stdin, cwd=cwd, env=env, shell=shell)
File “/usr/local/lib/python3.5/dist-packages/run/__init__.py”, line 121, in create_process
shlex.split(command),
File “/usr/lib/python3.5/shlex.py”, line 273, in split
return list(lex)
File “/usr/lib/python3.5/shlex.py”, line 263, in __next__
token = self.get_token()
File “/usr/lib/python3.5/shlex.py”, line 90, in get_token
raw = self.read_token()
File “/usr/lib/python3.5/shlex.py”, line 118, in read_token
nextchar = self.instream.read(1)
AttributeError: ‘tuple’ object has no attribute ‘read’
二、问题解决
网上相关的问题非常少,这个错误倒是很常见,但是都不是 pip 导致的,后来在 github 发现了一个 issue,这个人的问题跟我类似,也是 Pip does not install or uninstall.,看了看下面人的建议,说是安装的包引起的,而那个人就是因为安装了subprocess.run,这个包的某些接口跟 Python 3.5+ 严重冲突。老王后来看了下 subprocess.run 的 GitHub,发现这个项目已经 6 年没有更新了。
后来发现前段前几天确实有人在这台服务器上装了 subprocess.run 这个 package(history),我把这个 package 删除了就可以正常使用 pip 了。
另外,这里有个小插曲,因为 pip 坏了,自然 pip uninstall 就不能用了,可以通过 pip -V 看自己的 package 装在哪里,然后手动把文件删除即可。