Ubuntu环境下Gunicorn无法识别虚拟环境中的Python依赖
Flask+Gunicorn部署问题排查与解决
在Ubuntu 23.10上基于Nginx、Flask、Gunicorn部署的服务器,Python模块安装在venv虚拟环境中,此前部署正常,现在Gunicorn无法启动,报错找不到Flask模块。怀疑Gunicorn未使用指定的虚拟环境执行。
用户systemd配置文件
Description=description After=network.target [Service] User=<my user name> Group=www-data WorkingDirectory=/var/www/<website name>.org/<project name>/<project name>/ Environment="PATH=/home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/bin/" ExecStart=/home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/bin/gunicorn --workers 3 --bind unix:/var/www/<site name>/<project name>/<project name>/<project name>.sock wsgi:app [Install] WantedBy=multi-user.target
虚拟环境bin目录文件列表
activate activate.fish activate.ps1 flask normalizer pip3 pip3.11 python3 wheel wheel-3.11 activate.csh activate.nu activate_this.py gunicorn pip pip-3.11 python python3.11 wheel3 wheel3.11
Gunicorn报错信息
[2023-11-22 04:17:49 +0000] [95711] [INFO] Starting gunicorn 20.1.0 [2023-11-22 04:17:49 +0000] [95711] [INFO] Listening at: http://127.0.0.1:8000 (95711) [2023-11-22 04:17:49 +0000] [95711] [INFO] Using worker: sync [2023-11-22 04:17:49 +0000] [95712] [INFO] Booting worker with pid: 95712 [2023-11-22 04:17:49 +0000] [95712] [ERROR] Exception in worker process Traceback (most recent call last): File "/usr/lib/python3/dist-packages/gunicorn/arbiter.py", line 589, in spawn_worker worker.init_process() File "/usr/lib/python3/dist-packages/gunicorn/workers/base.py", line 134, in init_process self.load_wsgi() File "/usr/lib/python3/dist-packages/gunicorn/workers/base.py", line 146, in load_wsgi self.wsgi = self.app.wsgi() ^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() ^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/gunicorn/app/wsgiapp.py", line 58, in load return self.load_wsgiapp() ^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp return util.import_app(self.app_uri) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/gunicorn/util.py", line 384, in import_app mod = importlib.import_module(module) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/var/www/zf47r85u8jkg.org/<project name>/<project name>/__init__.py", line 1, in <module> from flask import Flask ModuleNotFoundError: No module named 'flask' [2023-11-22 04:17:49 +0000] [95712] [INFO] Worker exiting (pid: 95712) [2023-11-22 04:17:49 +0000] [95711] [INFO] Shutting down: Master [2023-11-22 04:17:49 +0000] [95711] [INFO] Reason: Worker failed to boot.
问题分析与解决
从报错信息看,Gunicorn确实在使用系统全局安装的版本(路径/usr/lib/python3/dist-packages/gunicorn),而非虚拟环境内的版本,导致无法找到虚拟环境中安装的Flask模块。问题出在systemd服务的执行上下文,即使指定了PATH,可能因为环境变量传递或执行方式的问题,导致Gunicorn调用了全局版本。
修复步骤:
确认虚拟环境内的依赖安装
手动激活虚拟环境并验证依赖:source /home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/bin/activate pip install flask gunicorn pip list | grep -E "Flask|gunicorn"确保输出中存在这两个模块。
修改systemd配置,强制使用虚拟环境Python执行Gunicorn
将ExecStart改为通过虚拟环境的Python调用Gunicorn,避免路径歧义:ExecStart=/home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/bin/python -m gunicorn --workers 3 --bind unix:/var/www/<site name>/<project name>/<project name>/<project name>.sock wsgi:app完善环境变量设置(可选)
在[Service]段添加虚拟环境标识,确保上下文明确:Environment="VIRTUAL_ENV=/home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/" Environment="PATH=/home/<user name>/.local/share/virtualenvs/<site name>-rbL82YaN/bin:$PATH"重新加载配置并重启服务
sudo systemctl daemon-reload sudo systemctl restart <your-service-name>.service验证服务状态
sudo systemctl status <your-service-name>.service同时检查socket文件是否生成:
ls -l /var/www/<site name>/<project name>/<project name>/<project name>.sock
内容的提问来源于stack exchange,提问作者Alex Michael
相关产品推荐
相关产品推荐

