你的python3安装已损坏。

我想从Ubuntu 16.04.5 LTS升级到18.04,所以运行了sudo do-release-upgrade命令。 在下载和解压缩bionic.tar.gz后,我得到了以下结果:
Can not upgrade 

Your python3 install is corrupted. Please fix the '/usr/bin/python3'
symlink.

我看到了如何修复“Python安装损坏”的问题?,所以我执行了sudo ln -sf /usr/bin/python3.6 /usr/bin/python3,以为这可能是一个类似的问题。但是这并没有起作用(错误信息仍然相同)。
我有几个Python版本:
$ ls /usr/lib | grep python
python2.7
python3
python3.5
python3.6

$ update-alternatives --display python3
python3 - auto mode
  link best version is /usr/bin/python3.6
  link currently points to /usr/bin/python3.6
  link python3 is /usr/bin/python3
/usr/bin/python3.5 - priority 1
/usr/bin/python3.6 - priority 2

我该如何修复python3


1重新安装呢(如接受的答案中所提到的)? - Kulfy
8个回答

我在Pop!_OS 18.04上遇到了这个问题,试图升级到18.10,结果发现问题出在符号链接/usr/bin/python上,而不是/usr/bin/python3。我之前将/usr/bin/python3.6配置为python(而不是python3)的替代选项,当我更改了这个设置后,就可以按预期运行do-release-upgrade了。
希望错误信息指向python而不是python3
之前,有个问题:
$ update-alternatives --display python
python - manual mode
  link best version is /usr/bin/python3.6
  link currently points to /usr/bin/python2.7
  link python is /usr/bin/python
/usr/bin/python2.7 - priority 1
/usr/bin/python3.6 - priority 2 

我是这样修复的:
$ sudo update-alternatives --remove-all python
$ sudo ln -sf /usr/bin/python2.7 /usr/bin/python

另请参见下面的评论,其中描述了一种更精确的解决方案,也更好地解释了正在发生的事情以及如何修复它。

6是的,我可以确认这个解决方案有效,这应该被接受为答案。 - Sumit Jain
6选择update-alternatives --remove-all python绝对是一个不必要的过度操作:你只需要使用update-alternatives --config pythonpython指向最新的python2.*(例如python2.7),然后使用update-alternatives --config python3python3指向特定的python3.6 —— 这是18.04版本的默认Python 3版本。 - KiriSakow
3如果你需要在Ubuntu 18.04升级到Python 3.7,不要在整个系统范围内进行升级,否则你很可能会遇到一些令人讨厌的小问题,比如gnome-terminalupdate-manager等重要工具。相反,使用虚拟环境(文档在这里在这里)。 - KiriSakow
@Kiri 有办法安装其他版本的Python,而不用替换系统中的版本。例如使用deadsnakes PPA - wjandrea
1@KiriSakow:update-alternatives --config python3无法工作,因为python3不是替代系统中的有效“链接组”。 - Daniel K.
1这是对我有效的方法。我同时安装了Python和Python3,指向的是Python3.6版本。我需要将/usr/bin/python重新指向Python2.6版本。 - LnxSlck
我的 /usr/bin/python 指向的是 Python 3.7 而不是 2.7,而我的 /usr/bin/python3 也指向了 3.7。将 /usr/bin/python 指向 2.7 后,解决了我的 Python3 损坏错误。 - mmv_sat
我也通过 sudo ln -s python2.7 python; sudo ln -s python3.5 python3 解决了这个问题。看起来 do-release-upgrade 不识别替代设置。python 和 python3 应该直接指向 python2.7 和 python3.5(对于 Ubuntu 16.04)。 - Chan Kim
1警告:不要执行 sudo update-alternatives --remove-all python 命令,它会破坏你的 Python 2,甚至可能影响到 Python 3。这是过度杀伤力的操作。 - ioaniatr
1@ioaniatr 我觉得这是有意为之的。但后面的 sudo ln 是用来修复它的。 - wjandrea

你需要在16.04版本中使用默认的Python 3版本。那就是3.5,而不是3.6。所以运行以下命令:
sudo ln -sf /usr/bin/python3.5 /usr/bin/python3

如果那行不通,尝试重新安装python3包。
sudo apt-get install --reinstall python3

顺便说一下,update-alternatives --display python3 应该会给你返回 update-alternatives: error: no alternatives for python3。在Ubuntu中,不同版本的Python并不是可供选择的替代品。

1很遗憾,它不起作用。 https://kempelen.dai.fmph.uniba.sk/python_headache.png 系统已经更新到最新版本,并且我已经重新安装了python和python3软件包,但问题仍然存在。这只发生在这台机器上,其他类似的机器升级都没问题。 - Palo
5@palo 我在想之前提到的重新安装命令可能并不会完全重新安装所有内容。请尝试使用 sudo apt-get install --reinstall python3 python3-minimal python3.5 python3.5-minimal - wjandrea
非常感谢您的快速回复。我按照您的建议尝试了,但是仍然出现相同的错误信息:“您的python3安装已损坏,请修复'/usr/bin/python3'符号链接”。卸载python3并不是一个很好的选择,因为它会影响太多依赖包。如果您有任何调查的想法,请告诉我,我会进行相应的调查。 - Palo
6这可能与我的同事在这台机器上安装的软件有关,存放在一些本地文件夹中。我看到里面有嵌入式的Linux系统用于树莓派,还有包含Python3.6的Miniconda3,以及/usr/local/python2.7。但是,which python命令显示的是/usr/bin/python,而pip命令则来自/usr/local/bin/pip。即使在/etc/environment中将/usr/local/...放在PATH的最后,仍然出现相同的消息。我注意到pyversions -d报告说:“/usr/bin/python与Python默认版本不匹配。必须重置为指向python2.7”。所以我替换了链接/usr/bin/python,让它指向... - Palo
5直接将路径更改为/usr/bin/python2.7,而不是/etc/alternatives/python,然后pyversions -d突然变得正常,do-release-upgrade也没有关于python的投诉,并按预期开始了升级过程!所以问题可能只是由于python到python2.7之间通过/etc/alternatives的这个间接双链接路径。 - Palo
1@Palo 啊,所以你找到了和最受欢迎的答案相同的解决方案。 - wjandrea
嗯,我觉得那个回答很令人困惑。首先,我不知道"Pop!_OS 18.04"是什么,而且我是从LTS 16.04升级到18.04,而不是从18.04升级到18.10。此外,我也不知道sudo update-alternatives --remove-all python可能会有什么后果,所以我没有去尝试,而是选择了一个容易撤销的小步骤。但是很好你提到了这一点。谢谢。 - Palo
并且最好能够修复升级脚本,以便:1)不报告关于python3链接的错误信息;2)能够自动检测,不会妨碍那些喜欢纠结于Python问题的可怜用户。我的意思是,如果有人发明了一种空格数量改变语义的语言,那个人肯定从未真正使用过计算机。 - Palo
在通过之前的答案(@J. B. Rainsberger)破坏了我的系统之后,这个方法实际上有效。我在我的Ubuntu-18.04中安装了多个版本的Python(3.4、3.6、3.10等等)。使用ls -l /usr/bin/python*命令查找丢失了符号链接的版本后,我使用了sudo ln -sf /usr/bin/python3.6 /usr/bin/python3,然后重新安装了python3来解决问题。谢谢。 - ioaniatr

这里没有一个答案似乎能够解释如何自己找到解决方案,所以我自己进行了一次探索,在我的情况下是在Ubuntu 18.04 LTS上的KDE Neon中检查do-release-upgrade

首先,我使用tracefile -w运行它,并发现实际的release-upgrade-scripts被下载到一个/tmp/ubuntu-release-upgrader-xxxxxxxx目录中。

在那个目录中使用grep,我在DistUpgradeController.py中找到了错误信息:

❯ grep --line-number --recursive --binary-files=without-match "python3 install is corrupted"
DistUpgradeController.py:426:                             _("Your python3 install is corrupted. "

所以我查看了周围的代码,发现使用了函数_pythonSymlinkCheck,跳转到那里并发现了问题的根源: 脚本期望符号链接/usr/bin/python3解析为/usr/bin/<debian_default_python>
binaries_and_dirnames = [("python3", "python3")]
for binary, dirname in binaries_and_dirnames:
    debian_defaults = '/usr/share/%s/debian_defaults' % dirname
    if os.path.exists(debian_defaults):
        config = SafeConfigParser()
        with open(debian_defaults) as f:
            config.readfp(f)
        try:
            expected_default = config.get('DEFAULT', 'default-version')
        except NoOptionError:
            logging.debug("no default version for %s found in '%s'" %
                          (binary, config))
            return False
        try:
            fs_default_version = os.readlink('/usr/bin/%s' % binary)
        except OSError as e:
            logging.error("os.readlink failed (%s)" % e)
            return False
        if not fs_default_version in (expected_default, os.path.join('/usr/bin', expected_default)):

从脚本中可以看出,<debian_default_python>/usr/share/python3/debian_defaultsDEFAULT部分的default-version键。
❯ cat /usr/share/python3/debian_defaults
[DEFAULT]
# the default python3 version
default-version = python3.6

我的链接确实指向了/usr/bin/python3.6,但是通过update-alternatives的额外间接方式,这个脚本无法解析:
❯ python
Python 3.6.9 (default, Jul 17 2020, 12:50:27)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.readlink("/usr/bin/python3")
'/etc/alternatives/python3'
>>> os.readlink("/etc/alternatives/python3")
'/usr/bin/python3.6'

所以最后我也不得不采取了核选项,而且现在对正在发生的一切都有充分的了解 :)
sudo ln -sf /usr/bin/python3.6 /usr/bin/python3

2我的天啊,错误信息本可以更好一些。为此浪费了成千上万个小时。这不是腐败的问题,而是版本不同。人们只会想到重新安装这个词。 - Pradip Vaghasiya
1看起来脚本的这部分现在已经修复了,因为它使用了os.path.realpath(),它可以递归地解析符号链接,而不像os.readlink()只能解析链中的第一个链接。 - wjandrea

我在运行WSL Ubuntu的Windows 10 1903上遇到了这个错误信息,当我想要从16.04 LTS升级到18.04 LTS时。
在do-release-upgrade失败后,我尝试了update-alternatives --config python提供的每个选择,并再次运行了升级命令。但是没有起到作用。
然后我检查了日志文件/var/log/dist-upgrade/main.log,其中包含以下内容:
2019-09-02 20:58:08,686 DEBUG _pythonSymlinkCheck run
2019-09-02 20:58:08,687 DEBUG python symlink points to: '/etc/alternatives/python', but expected is 'python2.7' or
'/usr/bin/python2.7'
2019-09-02 20:58:08,688 ERROR pythonSymlinkCheck() failed, aborting

所以尽管错误消息提到了python3,但问题实际上是关于python2
升级脚本检查的是/usr/bin/python链接到/usr/bin/python2,请参考这里的源代码:DistUpgrade/DistUpgradeController.py ubuntu launchpad
因此,一种解决方案是完全从替代系统中删除python,并手动添加链接,就像最受欢迎的答案中所描述的那样。
如果您不想从替代系统中删除python,只需在升级过程中更改链接即可。
# rm /usr/bin/python 
# ln -sf /usr/bin/python2.7 /usr/bin/python
# do-release-upgrade

这对我有效。
在升级过程中,链接会自动修复。因此,当升级完成后,它指向了"alternatives"目录中的Python入口点。
$ ls -l /usr/bin/python
lrwxrwxrwx 1 root root 24 Sep  2 22:01 /usr/bin/python -> /etc/alternatives/python

编辑:为了提供详细信息,如果您从18.04 LTS升级到19.04,该问题也可能出现,并且答案也适用于这种情况。

2注意:此答案同样适用于从Ubuntu 18.04 LTS升级到19.04的情况。我在成功完成18.04更新后亲自尝试过。 - Daniel K.
这对我有用。/usr/bin/python和/usr/bin/python3中的符号链接必须是绝对路径:tail /var/log/dist-upgrade/main.log显示2021-10-07 14:34:42,156 DEBUG python symlink points to: './python2.7', but expected is 'python2.7' or '/usr/bin/python2.7'。你需要保持并确保这三个python链接都是完整且绝对的:/usr/bin/python、/usr/bin/python2和/usr/bin/python3。 - michaeljtbrooks

基本上,解决此问题的方法包括使/usr/bin/python指向您的Ubuntu版本所期望的正确Python版本(例如,在16.04中为Python2.7,在18.04中为Python3.6)。
如果在系统中安装了多个Python版本,则可以使用update-alternatives来管理它们。无论您的Python默认备选项是否是系统期望的正确版本(在Ubuntu 18.04中为3.6),它都不起作用。
之所以这样做不起作用,原因在于使用update-alternatives时,/usr/bin/python3指向/etc/alternatives/python3,而似乎与使/usr/bin/python3指向/usr/bin/python3.6并不完全相同。
这就是为什么解决此问题的方法通常包括停止使用update-alternatives来管理Python3版本,并使/usr/bin/python3指向系统期望的正确版本的Python3的原因。

在干净的18.04安装中,/usr/bin/python不存在,但如果您选择升级而不是进行干净安装,或者安装python软件包,那么它将存在,并且应该是Python 2.7而不是3.6。请参阅PEP 394 - wjandrea
2清楚地说,Ubuntu上的Python的不同版本并不是替代品,也不应该使用update-alternatives来管理。这是因为操作系统依赖于特定的版本被安装。 - wjandrea
如果错误消息能报告实际的错误,而不是错误地设置了python3,而应该正确设置为python,那就太好了。 - FKEinternet

以下命令应该可以正常运行:
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2
sudo rm /usr/bin/python
sudo ln -s /usr/bin/python2.7 /usr/bin/python
sudo do-release-upgrade

我刚刚尝试升级到jammy(22.04),遇到了同样的错误。这个错误归结为升级程序包中的错误符号链接检查。我已经提交了一个带有修复方案的错误报告,在这里
为了解决这个问题,你可以让你的python3链接直接指向最终的可执行文件(而不是通过/etc/alternatives/python3进行绕行)。
sudo ln -s /usr/bin/python3.9 /usr/bin/python3

这是我尝试将我的xenial 16.04升级到18.04时的修复方法。
mkdir /usr/share/python2/
cp /usr/share/python/debian_defaults /usr/share/python2/debian_defaults
cd /usr/bin/python2 /usr/bin/python.27

否则,ubuntu-release-upgrader会显示类似的错误信息。
/usr/lib/python3$ sudo do-release-upgrade 
Checking for a new Ubuntu release
Get:1 Upgrade tool signature [819 B]                                                                                                                                                                               
Get:2 Upgrade tool [1,245 kB]                                                                                                                                                                                      
Fetched 1,245 kB in 0s (0 B/s)                                                                                                                                                                                     
authenticate 'bionic.tar.gz' against 'bionic.tar.gz.gpg' 
extracting 'bionic.tar.gz'

Reading cache

Checking package manager

Can not upgrade 

Your python3 install is corrupted. Please fix the '/usr/bin/python3' 
symlink. 

主要的日志文件位于
/var/log/dist-upgrade/main.log

在这里,升级程序报了个错。此外,你可能还想查看一下另一个文件,实际上它位于/tmp/ubuntu-release-upgrader/目录下。
less /tmp/ubuntu-release-upgrader/*/DistUpgradeController.py