备注:
开发环境下,如果要控制 Python 版本,建议使用更加稳定的 conda。安装以后的具体使用参照 Anaconda 的虚拟环境、包管理以及 kernel 加入 notebook。
1. 概述:
Ubuntu 自带的 Python 有时会产生奇怪的 bug,但是我们不能随便更换自带 Python,因为 Ubuntu 已经与自带 Python 深度绑定,动了自带 Python 会让系统不稳定。
解决办法是使用 Python 的版本控制工具 pyenv。pyenv 之于 Python,类似于 nvm 之于 Node.js。
2. 安装 pyenv
2.2 安装 Python 编译需要的依赖文件
sudo apt-get install -y build-essential libbz2-dev libssl-dev libreadline-dev libsqlite3-dev tk-dev
# for Numpy, Matplotlib, SciPy, etc.
sudo apt-get install -y libpng-dev libfreetype6-dev
2.2 安装 pyenv
根据 pyenv installer 中的介绍,安装方法有两种,这里用自动安装方法(而且会附带安装 pyenv-virtualenv 插件)。
curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
2.3 配置全局变量
把以下内容写入 ~/.bashrc
。如果后面不能使用,考虑放入 ~/.profile
或者 ~/.bash_profile
。
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
3. 使用 pyenv
3.1 安装你需要的 Python 版本
查看可以安装的 Python 版本
python pyenv install --list
安装指定版本,假设安装 Python 3.5.3
pyenv install 3.5.3
3.2 创建 Python 环境
使用 Python 3.5.3 创建一个叫 general 的环境。
pyenv virtualenv 3.5.3 general
查看现有虚拟环境
pyenv virtualenvs
进入虚拟环境 general
pyenv activate general
退出虚拟环境
pyenv deactivate
3.3 设置为全局环境
把刚才的 general 的环境设置为全局环境。
pyenv global general
如果创建了多个环境,查看已经创建了哪些环境,可以使用命令
pyenv versions
查看当前激活的版本(version 是单数)
pyenv version
4. 参考文章
4.1 pyenv 的 github 页面
pyenv
介绍 pvenv 使用与安装
4.2 Ubuntu 官网的文章
How do I install Python 3.6 using apt-get?
重点是 Nick T 的答案,值得参考
4.3 中文的 pyenv 使用介绍
pyenv及pyenv-virtual配置
Python版本管理:pyenv和pyenv-virtualenv(MAC、Linux)、virtualenv和virtualenvwrapper(windows)
Python 多版本共存之 pyenv
使用pyenv创建多版本python环境
4.4 该文提到服务器 ~/.bashrc 中可能无法生效的问题
解决FABRIC执行远程命令时无法加载PYENV的PYTHON环境
5. Ubuntu 自带 Python 的 BUG 以及解决办法
我在使用 Ubuntu 16.04 (Xenial) 的时候,Python 3.5.2 中,如果 Django 使用了 rest_framework 的时候,一旦 makemigrations 或者 migrate 就会报错 struct.error: unpack requires a bytes object of length 4
。
该 bug 促使我去寻找 Python 版本控制的方法。
(profiles_api) ubuntu@ubuntu-xenial:/vagrant/src/profiles_project$ python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 22, in
execute_from_command_line(sys.argv)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
utility.execute()
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/core/management/__init__.py", line 337, in execute
django.setup()
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models()
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 986, in _gcd_import
File "", line 969, in _find_and_load
File "", line 958, in _find_and_load_unlocked
File "", line 673, in _load_unlocked
File "", line 665, in exec_module
File "", line 222, in _call_with_frames_removed
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/contrib/auth/models.py", line 103, in
class Group(models.Model):
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/db/models/base.py", line 162, in __new__
new_class.add_to_class(obj_name, obj)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/db/models/base.py", line 330, in add_to_class
value.contribute_to_class(cls, name)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/db/models/fields/related.py", line 1648, in contribute_to_class
self.remote_field.through = create_many_to_many_intermediary_model(self, cls)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/db/models/fields/related.py", line 1104, in create_many_to_many_intermediary_model
'verbose_name': _('%(from)s-%(to)s relationship') % {'from': from_, 'to': to},
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/functional.py", line 162, in __mod__
return six.text_type(self) % rhs
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/functional.py", line 119, in __text_cast
return func(*self.__args, **self.__kw)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/__init__.py", line 89, in ugettext
return _trans.ugettext(message)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 338, in gettext
return do_translate(message, 'gettext')
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 321, in do_translate
_default = _default or translation(settings.LANGUAGE_CODE)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 228, in translation
_translations[language] = DjangoTranslation(language)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 129, in __init__
self._add_installed_apps_translations()
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 177, in _add_installed_apps_translations
translation = self._new_gnu_trans(localedir)
File "/home/ubuntu/virtualenvs/profiles_api/lib/python3.5/site-packages/django/utils/translation/trans_real.py", line 156, in _new_gnu_trans
fallback=use_null_fallback)
File "/usr/lib/python3.5/gettext.py", line 441, in translation
t = _translations.setdefault(key, class_(fp))
File "/usr/lib/python3.5/gettext.py", line 162, in __init__
self._parse(fp)
File "/usr/lib/python3.5/gettext.py", line 248, in _parse
magic = unpack('
该 bug 最主要的原因是没有升级 ubuntu 的包,运行一下命令即可
$ sudo apt-get update
$ sudo apt-get -y upgrade
$ sudo apt-get install -y python3-dev sqlite python-pip
$ sudo pip install --upgrade pip
$ sudo pip install virtualenvwrapper
以下命令写入 ~/.zshrc
中确保 virtualenvwrapper 可用。
WORKON_HOME=~/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh