1、版本环境、虚拟环境区别?
-
版本环境
-
版本环境的意思是可以控制当前python的全局版本号以及所有跟此版本号有关的lib
-
-
虚拟环境
-
为了隔离不同项目所依赖的python包,避免所有的项目依赖的包都放在同一个文件夹下面,造成版本依赖混乱,导致删不好删,改不好改,为了隔离不同项目的依赖包,对类似爬虫,人工智能、web等不同项目的包给予隔离而分离出来的环境,叫虚拟环境
-
-
两者混淆点
-
用不同的Python解释器,就可以创造出来两个Python版本的虚拟环境,例如用Python2生成的虚拟环境,就是基于Python2解释器的虚拟环境,用Python3生成的就是基于Python3解释器的虚拟环境,在使用 Pip安装包时,会对 Python 解释器版本进行区分和隔离,这样让初入门 Python的新手,总觉得两者有不可分割的关系,但对于同一个操作系统,如何有多个 Python 解释器,从 PHP 转过来的人估计不好理解,PHP 环境隔离还是挺麻烦的(仍然可以做到 wamp 就把 PHP分离了),从 Java 转过来的却很容易理解,因为 JDK 可以有多个,放在不同的位置,同理 Python 解释器也可以有多个,放在不同的位置,只需要用这些解释器来创建虚拟环境,就可以让不同的虚拟环境依赖不同 Python 版本的解释器。
-
2、软件包 | 包?
-
两者都可用pip来进行安装,只在虚拟环境情况下有较大分别
-
Python的软件包:是依赖于Python解释器的软件包,本身可能要编译以及执行,执行过程中可能调用Python解释器依赖的其他包,如果全局环境,例如使用 python 命令时,python 的版本号和虚拟环境的版本号不一致,则导致 Python 软件包报错,因为Pip安装时是按照虚拟环境的 Python 解释器版本安装的,执行时却是全局 Python 解释器执行,两者代码不兼容,则报错。
-
包:不是一个独立软件,只是在运行环境中,被项目加载并执行的代码集,只在虚拟环境启动时才被执行,但因为执行时会主动切换到虚拟环境中,所以不存在因为兼容问题报错的情况。
3、虚拟环境
-
虚拟环境的python解释器不是一个实际解释器,venv也不是完整的python解释器环境,可以理解为原基础环境的一个快捷方式,最终运行起来后,还是由原来生成虚拟环境的解释器进行解释,只不过在 form import 包时,是从虚拟环境的site-package中提取,而不是从Python 解释器根目录的site-package中提取,所以就保证了包的隔离。
-
因此vitualenv 解决的是虚拟环境的问题,如果操作系统只有python3,那么virtualenv只是为了不同项目而创建的不同虚拟环境而已,并不是拷贝了原始解释器以及解释器的依赖的各类包,虚拟环境中的解释器也无法代替原始解释器,因此通过pip安装的包里如果本身就是软件,而这个软件要依赖原始解释器,那么虚拟环境是运行不起来的,这个要明确,会报一些找不到依赖包的错误,因此非纯粹的 python 包(如uwsgi)不要在虚拟环境中用pip来安装,容易造成一种可以成功安装并执行的错觉
4、conda 和 virtualenv的区别
- virtualenv 主要工作是为不同项目分离不同的虚拟环境,至于虚拟环境依赖的python版本,virtualenv 是控制不了的,因为虚拟环境的解释器的快捷方式指向他的创造者
- conda 比 virtualenv 更强的一点在于,能将整个环境在执行 conda activate pythonXXX 时既创建了有个新的虚拟环境,也基于了一种版本环境
- python -m venv XXX 命令是 python3 编译器自带的一个创建虚拟环境的命令,与 virtualenv 的唯一区别是 virtualenv 还支持 python2
- conda 和 virtualenv 更强的一个功能是可以为这个新创建的版本环境装软件,对于像 uwsgi 这种软件来说,要基于原始 python 解释器进行安装,而不是在虚拟环境中,因此这里强调一点,conda 创建的既是一个虚拟环境又是一个独立的版本环境,在这个版本环境中,一切都是隔离独立的,这个是非常强的,因此 conda install uwsgi 可以为这个版本环境安装 uwsgi,当你用 pip install uwsgi 时,会安装到 Mac 原生环境根目录下,原因是 pip 并未做版本环境隔离,所以在版本环境中,使用 pip install uwsgi 时,编译器采用 mac 最原始的 python 解释器执行,这就造成版本错误,所以还是要用 conda install uwsgi -c conda-forge 来安装
- conda install uwsgi 和 pip install uwsgi 两者主要有以下几点区别:
安装的 Python 环境不同。
pip 默认为系统 Python,conda 允许创建独立的 Python 环境。
管理方案不同。pip 是 Python 的包管理器,conda 是跨语言的包环境管理器。
依赖处理不同。pip 只看 Python 依赖,conda 可以一并处理非 Python 依赖。
包来源不同。pip 默认 PyPI 源,conda 可指定不同渠道和来源。
isolation 隔离性。conda 环境可以实现不同 Python 版本和包之间的隔离。
具体到本题:
pip install uwsgi 会使用系统默认 Python 解释器和对应的 site-packages 路径进行安装。
而 conda install uwsgi 会使用conda环境内的 Python 解释器和 site-packages 进行安装,与系统 Python 隔离。
这是因为 conda 环境有自己独立的 Python 解释器和包路径,所以可以和系统 Python 完全隔离开来,避免冲突。
所以两者的 Python 环境和依赖管理方式不同,会导致 uwsgi 的安装使用不同的 Python 解释器和依赖。
6. 其他类似的 uwsgi 的软件包都应该采用 conda 进行安装,这样能保证这些执行软件的依赖被锁定在当前 python 的虚拟环境中
5、虚拟环境和版本环境不同导致的问题
-
如果虚拟环境用的是 python3.7 其安装的依赖包就是 3.7 的,而使用版本环境 3.8 来运行,有可能有包版本冲突问题
-
所以虚拟环境要和版本环境的解释器版本一致,那个版本环境创建的虚拟环境,就按照那个版本环境来运行 uwsgi,否则会出现版本不兼容,报代码错误问题
6、conda环境下安装并执行uwsgi正确方式
1)采用 conda 创建的版本环境 python3.8: conda create -n test python=3.8
2)conda(或source) activate test 进入test虚拟环境
3)执行 pip install -r requirement.txt 安装所有依赖包
4)接下来安装uwsgi:
pip install uwsgi 在conda环境下大概率安装不成功,可以使用一下命令代替:
conda install -c conda-forge uwsgi
运行uwsgi 有可能碰到 libiconv.so 动态库找不到的问题,同样可以用conda安装
conda install -c conda-forge libiconv
(-c 是渠道的意思,conda-forge 这个镜像渠道有很全的软件包)
5)uwsgi安装好后,需要在django项目根目录下建立一个名为uwsgi.ini的文件,在里面配置好uwsgi;然后进入项目目录下存放uwsig.ini文件的目录,创建/编辑配置文件 uwsig.ini
[uwsgi]
# 指定项目执行的端口号,用nginx的时候就要配socket,绑定的 UNIX socket socket=127.0.0.1:8000 #指定项目所在位置,在使用conda虚拟环境时需要这一条 pythonpath=/home/admin/test/ # python的安裝路径 home=/Users/senwang/workspace/python-api/venv/ # Django manage.py 所在文件夹路径 chdir = /home/user/projectname/ # module 或 wsgi-file:指定WSGI应用的入口。二选一,只写一个! # module参数通常用于指定Python模块及其WSGI应用对象, # 而 wsgi-file参数是项目上wsgi.py所在的位置,一般与settings目录相同 。 module = plus.wsgi:application # wsgi-file=/home/user/projectname//test/wsgi.py # 开启的进程数量 processes=1 # 开启的线程数量 threads=2 # 启用master进程管理 master = true # 最大请求处理数,之后重新生成进程 max-requests = 5000 # 指定存储master进程PID的文件路径。 pidfile = /var/run/uwsgi.pid # 日志,uwsgi无法启动时来这查看错误日志 daemonize=uwsgi.log # 当uWSGI服务器退出时,自动删除UNIX socket文件和PID文件。 vacuum = true
6)uwsgi配置好后,要启动uwsgi, 启动命令:
# 在存放有uwsig.ini文件的目录下 执行, 一定要在django实际使用的conda环境下,否则会报错
uwsgi --ini uwsgi.ini # 启动uwsgi,
uwsgi --stop uwsgi.pid # 停止uwsgi
uwsgi --reload uwsgi.pid # 重启uwsgi
7)uwsgi配置好后,要配置nginx:
首先安装nginx, 运行命令 sudo apt install nginx
nginx 命令:
sudo service nginx start 启动
sudo service nginx stop 停止
sudo service nginx restart 重启nginx
sudo nginx -s reload 重载配置文件
sudo nginx -s quit 优雅的停止nginx
sudo nginx -s term 停止nginx
sudo nginx -s reopen 打开一份新的日志
配置nginx:
在/etc/nginx/site-available下新建文件test.conf:
server { listen 8888; #nginx监听的端口 charset utf-8; client_max_body_size 75M; location / { uwsgi_pass 127.0.0.1:8000; # 与uwsgi中配置的相一致 include /etc/nginx/uwsgi_params; # proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }location /static/ { # 如果用到静态文件
alias /home/test/test/static/;
}}
8)然后要建立软连接:
sudo ln -s /etc/nginx/site-available/test.conf /etc/nginx/site-enabled/test.conf
9)最后用 sudo nginx -s reload 命令启动重载配置文件即可
10)最后, 如果需要配置负载均衡:
// http模块中配置upstream upstream test { server 127.0.0.1:8002 weight=2; server 127.0.0.1:8003 weight=1; } // 将server模块中的location替换为如下 location / { proxy_pass http://test; }
7、uWSGI的配置项:
在uWSGI的配置中,连接Python程序的配置主要通过uWSGI的配置文件(如uwsgi.ini
)来实现。这个配置文件详细指定了uWSGI如何与Python应用程序交互,包括Python应用程序的位置、入口点等信息。以下是一个清晰的配置示例和要点归纳:
1)配置文件示例
假设配置文件名为uwsgi.ini
,其内容可能如下:
[uwsgi] | |
module = your_app_module:app # Python应用的模块名和可调用对象名 | |
master = true # 启用主进程 | |
processes = 5 # 子进程数量 | |
socket = /tmp/uwsgi.sock # uWSGI与应用通信的socket文件路径 | |
chmod-socket = 660 # socket文件的权限 | |
vacuum = true # 退出时自动清理socket文件 | |
die-on-term = true # 在接收到终止信号时退出 | |
chdir = /path/to/your/project # 指定项目目录的路径(可选) | |
wsgi-file = your_project/wsgi.py # 指定WSGI文件的位置(如果module配置不适用) |
2)配置参数及作用
- module:
- 指定Python应用的模块名和可调用对象名。格式为
模块名:可调用对象名
。这是uWSGI加载Python应用的主要方式。
- 指定Python应用的模块名和可调用对象名。格式为
- wsgi-file (可选):
- 当
module
配置不适用时,可以通过wsgi-file
直接指定WSGI文件的路径。这个文件应该包含一个WSGI可调用对象,uWSGI将使用这个对象来接收和处理请求。
- 当
- chdir:
- 指定项目目录的路径。这个选项不是必须的,但有助于确保uWSGI能够正确地找到Python应用和其他相关文件。
- socket:
- 指定uWSGI与应用通信的socket文件路径或TCP端口。这是uWSGI与外部(如Web服务器)通信的关键配置。
- master:
- 是否启用主进程模式。在多进程部署时,这个选项有助于管理子进程。
- processes:
- 指定uWSGI将启动的子进程数量。这个数值可以根据应用的负载和服务器的性能进行调整。
- chmod-socket:
- 设置socket文件的权限。这有助于确保socket文件的安全性。
- vacuum:
- 指示uWSGI在退出时是否自动清理socket文件。这有助于避免留下无用的socket文件。
- die-on-term:
- 指定uWSGI在接收到终止信号时是否退出。这有助于优雅地关闭uWSGI服务。
8、nginx+uwsgi部署django项目时,无法访问可能的原因
- nginx配置文件未配置正确
server_name = xx.xx.xx.xx # 注意地址是否正确
# 注意配置的端口号,端口80时可省略端口:xx.xx.xx.xx[:80]
listen 80
# 注意路由转发端口是nginx端口,不是uwsgi转发端口(如8000) <-- 错的较多
location /api { ... } # 80端口时: xx.xx.xx.xx/api 非xx.xx.xx.xx:8000/api(以为是项目端口)
- uwsgi配置问题
module = xx.wsgi # xx一般与项目同名,可查看项目文件确认,在项目文件夹下第一层,固定格式xxx.wsgi
home = /xxx/xxx/xxx/xxx环境文件夹 # 运行环境路径,注意只到环境文件夹,即bin的上一层
一些方法帮助排查:
- 检查后端:
python manage.py runserver 0.0.0.0:8000
尝试项目是否可正常启动 - 检查uwsgi转发:
uwsgi --ini uwsgi.ini
手动启动uwsgi,直接访问后端看能否正常访问,以排除uwsgi的问题。注意socket和http的配置区别,如果使用http,并且开启了端口,可在浏览器直接访问做尝试。 - 检查nginx:将
location / {...}
中添加proxy_pass http://www.baidu.com;
,访问ip/域名,是否正常转发到百度,以排除nginx未正常启动