美文网首页
2021-07-07pyenv管理和同步python环境(开发-

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

作者: 卢冠男 | 来源:发表于2021-07-07 11:02 被阅读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
    
    • 解决方案
      LANGUAGE_CODE = 'zh_cn'
      LANGUAGE_CODE = 'zh-Hans' # - not _
      zh-Hans是简体中文 zh-Hant是繁体中文
      /data/app/pyenv/versions/3.8.1/envs/base38/lib/python3.8/site-packages/django/conf/locale
      django的所有语言文件都在上面的路径中,请自行选择要使用的语言文件

    问题:

    - 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和协议中传输的内容。

    • 升级 Django 1.10 之前的中间件
      class django.utils.deprecation.MiddlewareMixin¶
      Django 提供了 django.utils.deprecation.MiddlewareMixin 来方便创建同时兼容 MIDDLEWARE 和旧的 MIDDLEWARE_CLASSES 的中间件类,并支持同步和异步请求。Django 所包含的所有中间件类都兼容这两种配置。

    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之前没传会报错

    相关文章

      网友评论

          本文标题:2021-07-07pyenv管理和同步python环境(开发-

          本文链接:https://www.haomeiwen.com/subject/ukjoultx.html