【问题标题】:How to update-alternatives to Python 3 without breaking apt?如何在不破坏 apt 的情况下更新 Python 3 的替代方案?
【发布时间】:2017-08-21 02:48:29
【问题描述】:

前几天我决定让命令 python 默认启动 python3 而不是 python2。

所以我这样做了:

$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 2

$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 3

$ sudo update-alternatives --config python

$ sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.5   3         auto mode
  1            /usr/bin/python2.7   2         manual mode
  2            /usr/bin/python3.5   3         manual mode

Press <enter> to keep the current choice[*], or type selection number: 0

这一切都奏效了。伟大的! :)

$ python -V
Python 3.5.2

但不久之后,我意识到在安装和删除 python 包时我已经破坏了 apt/aptitude,因为 apt 期望它发生了 python2。

事情就是这样。

$ sudo apt remove  python-samba
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  samba-libs
Use 'sudo apt autoremove' to remove it.
The following packages will be REMOVED:
  python-samba
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 5,790 kB disk space will be freed.
Do you want to continue? [Y/n] 
(Reading database ... 187285 files and directories currently installed.)
Removing python-samba (2:4.3.11+dfsg-0ubuntu0.16.04.5) ...
  File "/usr/bin/pyclean", line 63
    except (IOError, OSError), e:
                             ^
SyntaxError: invalid syntax
dpkg: error processing package python-samba (--remove):
 subprocess installed pre-removal script returned error exit status 1
Traceback (most recent call last):
  File "/usr/bin/pycompile", line 35, in <module>
    from debpython.version import SUPPORTED, debsorted, vrepr, \
  File "/usr/share/python/debpython/version.py", line 24, in <module>
    from ConfigParser import SafeConfigParser
ImportError: No module named 'ConfigParser'
dpkg: error while cleaning up:
 subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
 python-samba
E: Sub-process /usr/bin/dpkg returned an error code (1)

最终我猜它希望 python2 作为默认值,所以我取消了我的更改如下:

$ sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.5   3         auto mode
  1            /usr/bin/python2.7   2         manual mode
  2            /usr/bin/python3.5   3         manual mode

Press <enter> to keep the current choice[*], or type selection number: 1

$ python -V
Python 2.7.12

然后 apt 再次工作

$ sudo apt remove  python-samba
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  samba-libs
Use 'sudo apt autoremove' to remove it.
The following packages will be REMOVED:
  python-samba
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
1 not fully installed or removed.
After this operation, 5,790 kB disk space will be freed.
Do you want to continue? [Y/n] 
(Reading database ... 187285 files and directories currently installed.)
Removing python-samba (2:4.3.11+dfsg-0ubuntu0.16.04.5) ...

所以我不得不让它默认为 python 2,但我在 python 3 中开发,所以希望我的系统在我运行 python 和空闲时默认为 python 3。

谁能告诉我如何在不破坏 apt 的情况下实现这一目标?

我的系统是运行 Ubuntu 的 Raspberry Pi 3B:

Linux mymachine 4.4.38-v7+ #938 SMP Thu Dec 15 15:22:21 GMT 2016 armv7l armv7l armv7l GNU/Linux

(其实是arm v8)

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"

【问题讨论】:

  • 离开 python 指向 python2 否则你会遇到很多的麻烦
  • 是的,谢谢,我也这么想。 :)
  • 这个问题的答案需要更新。我目前正在运行默认使用 python3 的 Debian(通过 update-alternatives),我没有遇到任何问题。如果将来出现问题,我会发表评论,但趋势是它将成为新的默认值。

标签: python linux ubuntu debian apt


【解决方案1】:

根据 Debian 政策,python 指的是 Python 2,python3 指的是 Python 3。不要尝试在整个系统范围内更改此设置,否则您将遇到您已经发现的那种麻烦。

虚拟环境允许您使用任何版本的 Python 和所需的任何库运行独立的 Python 安装,而不会弄乱系统 Python 安装。

在最近的 Python 3 中,venv 是标准库的一部分;对于旧版本,您可能需要安装 python3-venv 或类似的软件包。

$HOME~$ python --version
Python 2.7.11

$HOME~$ python3 -m venv myenv
... stuff happens ...

$HOME~$ . ./myenv/bin/activate

(myenv) $HOME~$ type python   # "type" is preferred over which; see POSIX
python is /home/you/myenv/bin/python

(myenv) $HOME~$ python --version
Python 3.5.1

一种常见的做法是为您从事的每个项目都有一个单独的环境,无论如何;但如果您希望它看起来像您自己的登录有效的系统范围,您可以将激活节添加到您的 .profile 或类似内容中。

【讨论】:

  • 现在有点过时了;不同的发行版对此略有不同。例如,在 Ubuntu 上,python 现在可以指代python2python3(或者,我猜两者都不是),并且系统实用程序必须拼出python2python3
  • 实际上python3-venv 在 Debian 上被故意拆分为一个单独的包。它是 Python 标准库的一部分,但 Debian 决定将其设为可选。
  • 这不是问题的答案,而是 alternative 。有充分的理由支持和反对使用 venv。我的团队选择不这样做
【解决方案2】:

替换

[bash:~] $ sudo update-alternatives --install /usr/bin/python python \
/usr/bin/python2.7 2

[bash:~] $ sudo update-alternatives --install /usr/bin/python python \
/usr/bin/python3.5 3

[bash:~] $ sudo update-alternatives --install /usr/local/bin/python python \
/usr/bin/python2.7 2

[bash:~] $ sudo update-alternatives --install /usr/local/bin/python python \
/usr/bin/python3.5 3

例如安装到 /usr/local/bin 而不是 /usr/bin

并确保 /usr/local/bin 在 PATH 中位于 /usr/bin 之前。

[bash:~] $ echo $PATH
/usr/local/bin:/usr/bin:/bin

通过添加确保始终如此

export PATH=/usr/local/bin:$PATH

到您的 ~/.bashrc 文件的末尾。通常建议在 PATH 环境变量前面加上 /usr/local/bin/opt/&lt;some install&gt;/bin 等自定义 bin 文件夹,以确保在默认系统之前找到自定义项。

【讨论】:

  • 我不会对此投反对票,因为它可能在某些情况下有效;但真的,不要这样做。
  • @tripleee 为什么不呢?我希望系统级 python 不引用用户的 $PATH 来选择 python 可执行文件。当然,那些只是使用 /usr/bin/python 和 /usr/bin/python3,对吧?我看不出引入用户级别更改并将符号链接添加到 /usr/local/bin 会导致问题。
  • 因为update-alternatives 是错误的,所以永远不要用它来替换python 版本2 为python3。该问题描述了一些有据可查的症状。
  • 所以,这取决于 Ubuntu 中的软件如何查找 python 可执行文件。我的假设是系统进程不会简单地查看 $PATH,因为它依赖于用户。而update-alternatives 唯一要做的就是在/usr/local/bin/python 创建一个符号链接。 /usr/bin 没有任何变化。只要apt(或类似的)正在寻找/usr/bin/python 而不仅仅是python,应该没问题。我已经用 apt 对此进行了测试,看起来还不错。不过,这并不能保证它适用于所有系统软件!
  • 我怀疑它是否可以移植。您正在安装从/usr/local/bin/python/etc/alternatives/python 的符号链接,但后者已用于指向系统 Python,并且更改其链接目标也会更改系统 Python。 (不过,我无法验证这一点。)Ubuntu 的update-alternatives 是一个重新实现,因此它可能与 Debian 的工作方式不同。无论如何,我不明白您为什么要使用系统范围的alternatives 系统来管理/usr/local/bin 中的符号链接;只需手动创建符号链接。
【解决方案3】:

因为我不想破坏任何东西,所以我这样做是为了能够使用比 Python v3.4 更新的 Python3 版本:

$ sudo update-alternatives --install /usr/local/bin/python3 python3 /usr/bin/python3.6 1
update-alternatives: using /usr/bin/python3.6 to provide /usr/local/bin/python3 (python3) in auto mode
$ sudo update-alternatives --install /usr/local/bin/python3 python3 /usr/bin/python3.7 2
update-alternatives: using /usr/bin/python3.7 to provide /usr/local/bin/python3 (python3) in auto mode
$ update-alternatives --list python3
/usr/bin/python3.6
/usr/bin/python3.7
$ sudo update-alternatives --config python3
There are 2 choices for the alternative python3 (providing /usr/local/bin/python3).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.7   2         auto mode
  1            /usr/bin/python3.6   1         manual mode
  2            /usr/bin/python3.7   2         manual mode

Press enter to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/bin/python3.6 to provide /usr/local/bin/python3 (python3) in manual mode
$ ls -l /usr/local/bin/python3 /etc/alternatives/python3 
lrwxrwxrwx 1 root root 18 2019-05-03 02:59:03 /etc/alternatives/python3 -> /usr/bin/python3.6*
lrwxrwxrwx 1 root root 25 2019-05-03 02:58:53 /usr/local/bin/python3 -> /etc/alternatives/python3*

【讨论】:

    【解决方案4】:

    不知何故,python 3 回来了(经过一些更新?)并导致 apt 更新出现大问题,所以我决定完全从替代方案中删除 python 3:

    root:~# python -V
    Python 3.5.2
    
    root:~# update-alternatives --config python
    There are 2 choices for the alternative python (providing /usr/bin/python).
    
      Selection    Path                Priority   Status
    ------------------------------------------------------------
    * 0            /usr/bin/python3.5   3         auto mode
      1            /usr/bin/python2.7   2         manual mode
      2            /usr/bin/python3.5   3         manual mode
    
    
    root:~# update-alternatives --remove python /usr/bin/python3.5
    
    root:~# update-alternatives --config python
    There is 1 choice for the alternative python (providing /usr/bin/python).
    
        Selection    Path                Priority   Status
    ------------------------------------------------------------
      0            /usr/bin/python2.7   2         auto mode
    * 1            /usr/bin/python2.7   2         manual mode
    
    Press <enter> to keep the current choice[*], or type selection number: 0
    
    
    root:~# python -V
    Python 2.7.12
    
    root:~# update-alternatives --config python
    There is only one alternative in link group python (providing /usr/bin/python): /usr/bin/python2.7
    Nothing to configure.
    

    【讨论】:

    • 确实,python3 不是 python 的有效替代品,因为它需要引用 Python 2。
    • 当初设置的时候告诉系统python3的优先级高于python2。然后你手动将它设置为 python 2。似乎有什么东西让它回到了自动模式,所以选择了 python3。因此,删除 python3 可能是正确的做法,但将其设置为较低的优先级会产生类似的效果。如果是我,我可能会从 update-alternatives 中删除这两个条目,以使其恢复到系统启动的方式,实际上。未来出现混乱或问题的可能性较小。
    【解决方案5】:

    对于现在在 2021 年发现此问题的任何人来说,几乎所有早期的答案都已过时。

    /usr/bin/python 指向 Python 3 非常好,并且现在可以预期。Python 2 没有更新安全修复程序,因此任何仍在使用它的系统都应该升级为使用 Python 3 作为系统 Python。任何现代发行版都应该已经解决了将系统 Python 升级到 Python 3 的潜在不兼容问题。

    【讨论】:

    • 问题是关于python3的多个版本,并且缺乏正确的答案。例如,安装更新版本的 Python3 后,gnome-terminal 可能随时中断。
    • 所问的问题与 Python 3 版本之间的差异无关;它特别是关于让python 在不从 Python 2 升级系统的情况下运行 Python 3。对于不同的问题,这里没有“正确答案”也就不足为奇了。
    • Raspberry Pi OS (Debian) 在我的最新系统上仍然将 python2 (Python 2.7.16) 作为系统默认值:Raspbian GNU/Linux 10 (buster)
    • 您应该将其报告为安全漏洞。
    • 这是不正确的(您仍然可以通过重定向符号链接来破坏工作和支持的操作系统)。 FWIW: Canonical still maintains and ships Python 2 security updates for Ubuntu 18.04 LTS。示例:ubuntu.com/security/notices/USN-4754-4
    【解决方案6】:

    我已经编辑了 /home/user/.bashrc

    alias python27=/usr/bin/python2.7
    alias python31=/usr/bin/python3.10
    

    在 linux ubuntu 20.xx 上。我已将其添加到文档的最后。

    这会将 python27 绑定到您想要的版本。

    python27 pythonscrypt.py
    

    测试样本

    python27 --version
    

    但我想知道python和python3是否应该指向/usr/local/python3.9?

    我认为习惯上将 2.7-2.8 作为 python,将 3.9.x 作为 python3。

    从上面的帖子更新替代品对我来说有点不稳定,所以必须通过将默认值设置为正常来回溯一些。也正在尝试 anaconda 并且某些部分在 python 和 anaconda 版本之间变得有点混乱。

    但我认为编辑 .bashrc 然后退出终端并重新登录是 2021 年的最佳解决方案。

    保存更改后不要忘记退出终端并重新登录!

    另一种技术是在 python3 中使用 envs。

    【讨论】:

      猜你喜欢
      • 2017-09-14
      • 2010-10-15
      • 2018-03-08
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      相关资源
      最近更新 更多