2021-07-07pyenv管理和同步python环境(开发-

2021-07-07  本文已影响0人  卢冠男

pyenv概念

pyenv根据shell、项目目录、全局(global)三个环境定义,去调用不同环境的python版本和第三方包。

# shell:base38假设是我们新的环境名称
#该命令会同步在当前的shell窗口创建一个PYENV_VERSION的环境变量,作用域仅仅在当前的shell
pyenv shell base38
# 项目目录:某个项目需要特定的python版本
# 该命令会同步在项目目录下,创建一个.python-version的文件
pyenv local base38
# 或者 echo "base38" > .python-version
# 全局(global):
# 该命令会同步在pyenv的根目录(默认是~/.pyenv/)下创建一个version的文件
pyenv global base38

因此要在生产环境采用不同的python环境,这里推荐python路径采用:

/data/app/pyenv/shims/python

然后用.python-version文件来控制不同项目文件夹下的环境

升级和部署django-web项目:

在测试、生产等无网络环境进行安装和升级python版本,具体的流程和脚本如下:

升级环境

升级环境需要三个过程:开发机器上准备环境,打包pyenv进行迁移,启动web项目

解压、安装pyenv环境包
安装libcom文件
安装openssl 1.1

开发机器上准备环境

1安装pyenv环境包

# 新环境安装
sudo yum update
sudo yum install libffi-devel
sudo yum install openssl readline gcc patch readline-devel zlib-devel sqlite-devel openssl-devel bzip2-devel
sudo yum install mariadb-devel

#默认都已经上传了pyenv-master.zip,Python-3.8.1.tar.xz,pyenv-virtualenv-master.zip
# 安装pyenv
sudo su - app
mkdir -p /data/app
cd /data/app
sudo rm -r /data/app/pyenv
unzip pyenv-master.zip
mv pyenv-master pyenv

# 安装pyenv
echo 'export PATH=/data/app/pyenv/bin/:$PATH' >> ~/.bash_profile
echo 'export PYENV_ROOT=/data/app/pyenv' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile # 重启也会生效,接管Python

# 安装pyenv-virtualenv
unzip pyenv-virtualenv-master.zip
mv pyenv-virtualenv-master /data/app/pyenv/plugins/pyenv-virtualenv
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile
source ~/.bash_profile
pyenv virtualenv --version

2 安装python环境

# 从零安装python3
mkdir -p pyenv/cache
cp Python-3.8.1.tar.xz pyenv/cache/Python-3.8.1.tar.xz
rm pyenv/plugins/python-build/share/python-build/3.8.1
echo 'install_package "Python-3.8.1" "/data/app/pyenv/cache/Python-3.8.1.tar.xz" ldflags_dirs standard verify_py38 ensurepip' >> pyenv/plugins/python-build/share/python-build/3.8.1
pyenv install 3.8.1

3 安装其它第三方库

# 安装其他包:
# pip 设置

mkdir -p ~/.pip
echo '[global]' >> ~/.pip/pip.conf
echo 'index-url = http://mirrors.tencentyun.com/pypi/simple' >> ~/.pip/pip.conf
echo 'trusted-host=mirrors.tencentyun.com' >> ~/.pip/pip.conf
pip install --upgrade pip

# 重要==>克隆基础包后,创建其他模块的所需环境
pyenv virtualenv 3.8.1 base38
pyenv versions
pyenv shell base38 #<=====此命令行需要在安装pyenv后长开或者文末的版本指定写到配置文件中
pip install -r requirements.txt
pip install matplotlib
pip install mmh3,filterpy
pip install peewee

4 配置开发环境的应用环境变量

# 配置应用的环境变量
echo 'base38' > /data/app/.python-version
# # 免修改代码的Python路径
# ln -s /data/app/pyenv/shims/python /data/app/python/bin/python

打包pyenv进行迁移

1 打包传输

# 新环境准备完毕!!!
# 迁移环境
# 打包
tar -zcvf pyenv.tar.gz pyenv
# 传输
scp pyenv.tar.gz app@x.x.x.x:/data/app/

2 测试生产等新环境的准备

# python3 
sudo yum update
sudo yum install libffi-devel
sudo yum install openssl readline gcc patch readline-devel zlib-devel sqlite-devel openssl-devel bzip2-devel
sudo yum install mariadb-devel
sudo yum install -y xz-devel
# 安装pyenv
sudo su - app
mkdir -p /data/app
cd /data/app
tar -zxvf pyenv.tar.gz

echo 'export PATH=/data/app/pyenv/bin/:$PATH' >> ~/.bash_profile
echo 'export PYENV_ROOT=/data/app/pyenv' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile
source ~/.bash_profile # 重启也会生效,接管Python

pyenv versions
echo 'base38' > /data/app/.python-version

3 如果有多台机器需要安装pyenv迁移可以用下面的脚本:

#!/bin/bash  
#同步uat环境 
list="x.x.x.x y.y.y.y"   
for remote_host in $list;  
do  
echo $remote_host run start ;  
cd /data/app
scp pyenv.tar.gz $remote_host:/data/app
echo "ssh remote"
ssh $remote_host  << remotessh
cd /data/app
tar -zxvf pyenv.tar.gz

echo 'export PATH=/data/app/pyenv/bin/:\$PATH' >> ~/.bash_profile
echo 'export PYENV_ROOT=/data/app/pyenv' >> ~/.bash_profile
echo 'eval "\$(pyenv init -)"' >> ~/.bash_profile
echo 'eval "\$(pyenv virtualenv-init -)"' >> ~/.bash_profile
source ~/.bash_profile # 重启也会生效,接管Python
pyenv versions
echo 'base38' > /data/app/.python-version
echo "install OK!"
exit
remotessh
echo "ssh remote closed"
echo $remote_host run stop ; 
done

启动web项目

1、代码层面的python2-3的代码升级

2、安装一些新的依赖

升级过程中遇到的一些问题如下,可以进行参考

升级过程遇到的问题可以这里记录一下,后期我会再整理一下。

问题:

问题:

No translation files found for default language zh-cn

问题:

- TypeError: __init__() missing 1 required positional argument: 'on_delete' happens when your foreign key field doesn't have on_delete argument.

,on_delete=models.CASCADE
product = models.ForeignKey('product',db_column='product',db_constraint=False,on_delete=models.CASCADE)

As you know, from Django 2.0 on_delete is required.
you need to add the on_delete parameter.
A many-to-one relationship. Requires two positional arguments: the class to which the model is related and the on_delete option.
https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ForeignKey
monitor_mapped_name\curve_data 需要注意一下@benji

问题:

cannot import name 'available_attrs' from 'django.utils.decorators' 

去掉from django.utils.decorators import available_attrs

Since we expect apps to drop Python 2 compatibility we’re removing these APIs at this time.
If the @wraps() in your sample line is the standard functools.wraps() decorator, then you can just entirely remove assigned=available_attrs(...), because functools.WRAPPER_ASSIGNMENTS is the default value for assigned:
@wraps(view_func)
-> @wraps(view_func) otherwise, just use functools.WRAPPER_ASSIGNMENTS directly.

问题:

No module named 'django.utils.six'

views.py 里面的 from django.utils import six 也需要改为 import six

from django.utils.six.moves.urllib.parse import urlparse

from six.moves.urllib.parse import urlparse

问题:

'Specifying a namespace in include() without providing an app_name '
url(r'^iea/', include('iea.urls', namespace="iea"))

url(r'^iea/', include(('iea.urls', "iea"),namespace="iea"))
def include(arg, namespace=None):
urlconf_module, app_name = arg,arg就是那个元组,且给app_name赋值了

问题:

'WSGIRequest' object has no attribute 'user'

将MIDDLEWARE_CLASSES改成MIDDLEWARE
这是由于Django版本的问题,在1.10之前,中间件的key为MIDDLEWARE_CLASSES;在1.10之后,中间件的key为MIDDLEWARE。

问题:

get_wsgi_application :InterceptIllegalUserMiddleware() takes no arguments

class xxxxx(MiddlewareMixin): 继承MiddlewareMixin进行兼容

WSGI全称是Web Server Gateway Interface,其主要作用是Web服务器与Python Web应用程序或框架之间的建议标准接口,可以将WSGI协议分成三个组件Application,Server,Middleware和协议中传输的内容。

mixin 提供了一个 init() 方法,它需要一个 get_response 参数,并将其存储在 self.get_response 中。

call() 方法:

调用 self.process_request(request) (如果被定义过)。
调用 self.get_response(request) 来从后续的中间件和视图得到响应。
调用 self.process_response(request, response) (如果被定义过)。
返回响应。
如果和 MIDDLEWARE_CLASSES 一起使用,call() 方法将永远不会被使用;Django 会直接调用 process_request() 和 process_response() 。

在大多数情况下,从这个 Mixin 中继承就足以使一个旧式中间件与新系统兼容,并具有足够的向后兼容性。新的短路语义对现有中间件无害甚至有益。在少数情况下,中间件类可能需要一些改变来适应新的语义。

MIDDLEWARE 和 MIDDLEWARE_CLASSES 在使用上有些行为差异:这里需要测试是否有异常

MIDDLEWARE_CLASSES 下,每个中间件将始终调用它的 process_response 方法,即使早期的中间件通过从其 process_response 方法返回响应而短路。MIDDLEWARE 下,中间件行为更像洋葱:响应在输出时经过的层与在输入时看到请求的层相同。如果一个中间件短路,只有那个中间件和之前的中间件可以看到响应。
在 MIDDLEWARE_CLASSES 下,process_exception 应用于中间件 process_request 方法引发的异常。在 MIDDLEWARE 下,process_exception 只应用于视图引发的异常(或者从 TemplateResponse 的 render 方法引发的异常)。中间件引发的异常被转换为合适的 HTTP 响应,然后传递到下一个中间件。
MIDDLEWARE_CLASSES 下,如果 process_response 方法引发了异常,所有更早之前的中间件的 process_response 方法会被跳过,并一直返回 500 Internal Server Error 的 HTTP 响应(即使引发的异常是例如 Http404 )。在 MIDDLEWARE ,一个中间件引发的异常将立刻被转换为合适的 HTTP 响应,然后下一个中间件将看到响应。中间件不会因为中间件引发异常而被跳过。

问题:

django报错‘staticfiles‘ is not a registered tag library

修改前端模板为{% load static %},在html文件中
因为在django3.x中这部分做了修改,对于:
{% load staticfiles %}
{% load static from staticfiles %}
{% load admin_static %}

问题:

VariableDoesNotExist: Failed lookup for key [request] in u'[{}]'

t.render({"username":request.user.username,'next':''})
必须传入渲染的参数,login之前没传会报错

上一篇下一篇

猜你喜欢

热点阅读