如何在不破坏 apt 的情况下更新 Python3的替代品?

有一天,我决定将命令 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

然后又成功了

$ 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) ...

所以我不得不把它默认设置为 python2,但是我是在 python3中开发的,所以当我运行 python 和空闲时,我希望我的系统默认设置为 python3。

有人能告诉我,如何才能做到这一点,而不破坏公寓?

我的系统是一个运行 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

(这实际上是一个手臂 V8)

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

Somehow python 3 came back (after some updates?) and is causing big issues with apt updates, so I've decided to remove python 3 completely from the alternatives:

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.

Per Debian policy, python refers to Python 2 and python3 refers to Python 3. Don't try to change this system-wide or you are in for the sort of trouble you already discovered.

Virtual environments allow you to run an isolated Python installation with whatever version of Python and whatever libraries you need without messing with the system Python install.

With recent Python 3, venv is part of the standard library; with older versions, you might need to install python3-venv or a similar package.

$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

A common practice is to have a separate environment for each project you work on, anyway; but if you want this to look like it's effectively system-wide for your own login, you could add the activation stanza to your .profile or similar.

replace

[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

with

[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

e.g. installing into /usr/local/bin instead of /usr/bin.

and ensure the /usr/local/bin is before /usr/bin in PATH.

i.e.

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

Ensure this always is the case by adding

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

to the end of your ~/.bashrc file. Prefixing the PATH environment variable with custom bin folder such as /usr/local/bin or /opt/<some install>/bin is generally recommended to ensure that customizations are found before the default system ones.

As I didn't want to break anything, I did this to be able to use newer versions of Python3 than Python v3.4 :

$ 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*

For anyone finding this question now in 2021, pretty much all of the earlier answers are obsolete.

It is perfectly fine, and expected now, for /usr/bin/python to point to Python 3. Python 2 is not being updated with security fixes, so any system still using it should be upgraded to use Python 3 as the system Python. Any modern distribution should already have solved potential incompatibilities in upgrading the system Python to Python 3.

I've edited /home/user/.bashrc with

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

on linux ubuntu 20.xx. I've added it to the very end of the document.

this binds python27 to the version you want.

python27 pythonscrypt.py

Test the sample with

python27 --version

but I was wondering if python and python3 should be pointing to the /usr/local/python3.9?

I thought it was customary to have 2.7-2.8 as python and 3.9.x as python3.

Updating the alternatives from above post has it a bit wonky for me so have to backtrack some by setting defaults to normal. Also was trying anaconda and some parts were getting a bit confusing between python and anaconda versions.

But I think editing the .bashrc then exiting terminal and logging back in is the best solution in 2021.

Don't forget to exit terminal and log back in after saving changes!

Another technique would be using envs in python3.

Complementary to the full explications above, here is a small script to add all python versions so that you can just copy paste this.

i=0 ; for p in /usr/bin/python*.* ; do
update-alternatives --install /usr/bin/python python $p $((5 + i))
i=$((i+1))
done
update-alternatives --config python