结论: 在服务器上跑 Python 程序的标准流程是:用 python3 -m venv 建独立虚拟环境隔离依赖,用 pip 安装 requirements,Web 类应用交给 Gunicorn(或 uWSGI)以 WSGI 方式启动,再用 systemd 或 Supervisor 做进程守护,最后由 Nginx 反向代理对外提供 80/443 服务。切忌用 root 直接 python app.py 挂在后台。
引言:从"能跑起来"到"能稳定跑"
在服务器上运行 Python 程序有两个阶段。第一阶段是"跑起来"——python3 app.py 看到输出就算成功;第二阶段是"稳定跑"——SSH 断开不中断、崩溃能自动拉起、开机能自启、日志可追溯、多版本依赖不打架。绝大多数人卡在第二阶段。
本文以 Ubuntu 24.04 LTS(默认 Python 3.12)为例,覆盖 Web 应用(Flask / Django / FastAPI)与常驻脚本两类场景,给出从虚拟环境到 systemd 守护的完整链路。截至 2026 年,这套组合仍是 Python 服务端部署的主流做法。
Python 程序的运行方式怎么选?
先给结论:选型取决于程序类型与规模,不要一上来就用最重的方案。
| 方式 | 适用 | 优点 | 缺点 |
|---|---|---|---|
python3 xxx.py | 一次性脚本、调试 | 零配置 | 终端断开即退出 |
nohup / screen | 临时测试 | 简单 | 崩溃不重启,无开机自启 |
| Gunicorn + systemd | Flask/Django 生产(推荐) | 多进程、自动重启、日志规范 | 需写单元文件 |
| uWSGI + Nginx | 高并发、需 uwsgi 协议 | 性能强、功能全 | 配置复杂 |
| Supervisor | 多进程统一管理 | 自带进程组与 Web 面板 | 额外装组件 |
| Docker | 多应用隔离交付 | 环境一致性最好 | 需掌握容器技术 |
判断标准很简单:Web 服务用 Gunicorn + systemd(或 Supervisor);一次性脚本用 cron + venv;多服务混布、要求环境一致性时用 Docker。
第一步:安装 Python 与创建虚拟环境
结论:永远不要在系统的全局 Python 环境里装业务依赖。虚拟环境(Virtual Environment)是 Python 部署的第一原则。
sudo apt update
sudo apt install -y python3 python3-venv python3-pip python3-dev build-essential
python3 --version # Ubuntu 24.04 为 Python 3.12
which python3重要提示:Ubuntu 24.04 启用了 PEP 668 的"外部管理环境(externally-managed-environment)"标记,直接执行 pip install xxx 会报错 error: externally-managed-environment。这不是故障,而是系统在提醒你别污染全局环境。正确做法是建虚拟环境(不要用 --break-system-packages,除非你明确知道在做什么)。
# 建一个统一的虚拟环境存放目录
sudo mkdir -p /opt/venvs
sudo python3 -m venv /opt/venvs/myapp
# 激活(激活后命令行前面会出现 (myapp))
source /opt/venvs/myapp/bin/activate
# 升级 pip 并安装依赖
python -m pip install --upgrade pip wheel setuptools
pip install -r /opt/apps/myapp/requirements.txt
# 退出虚拟环境
deactivate虚拟环境的关键认知:
- 不需要"激活"也能用,直接调用绝对路径更稳妥,尤其是在 systemd 与 crontab 中:
/opt/venvs/myapp/bin/python /opt/apps/myapp/app.py。 - 依赖清单用
pip freeze > requirements.txt导出,生产环境建议锁定版本号(flask==3.0.3)。 - 虚拟环境目录可以整体打包迁移,但跨机器迁移含 C 扩展的包时需重新编译,最好在同版本系统上操作。
第二步:用 Gunicorn 启动 Web 应用
结论:Flask、Django 自带的开发服务器(app.run())是单线程、无优化的,绝对不能用于生产。生产必须用 WSGI 服务器(WSGI Server),Gunicorn 是最通用的选择。
source /opt/venvs/myapp/bin/activate
pip install gunicorn
# Flask:模块名:应用实例名
gunicorn -w 4 -k gthread --threads 2 -b 127.0.0.1:8000 'app:app'
# Django:项目包.wsgi
gunicorn -w 4 -b 127.0.0.1:8000 'myproject.wsgi:application'
# FastAPI(ASGI,需用 uvicorn worker)
pip install uvicorn[standard]
gunicorn -w 4 -k uvicorn.workers.UvicornWorker -b 127.0.0.1:8000 'main:app'参数含义:
-w 4:工作进程数,经验公式为 CPU 核心数 × 2 + 1;2 核机器设 4~5 即可,过多反而因内存与上下文切换变慢。-k gthread:使用线程 worker,配合--threads提升 IO 密集型场景吞吐。-b 127.0.0.1:8000:只监听本机,由 Nginx 对外,避免直接暴露。--timeout 60:worker 无响应超过该秒数会被重启,处理长任务时需调大。
生产环境建议把参数写进配置文件,便于版本管理:
# /opt/apps/myapp/gunicorn.conf.py
bind = "127.0.0.1:8000"
workers = 4
worker_class = "gthread"
threads = 2
timeout = 60
graceful_timeout = 30
keepalive = 5
max_requests = 2000 # 处理 N 个请求后自动重启 worker,缓解内存泄漏
max_requests_jitter = 200
accesslog = "/var/log/myapp/access.log"
errorlog = "/var/log/myapp/error.log"
loglevel = "info"
preload_app = True # 预加载应用,节省内存并可在启动时暴露错误sudo mkdir -p /var/log/myapp && sudo chown www-data:www-data /var/log/myapp
/opt/venvs/myapp/bin/gunicorn -c /opt/apps/myapp/gunicorn.conf.py 'app:app'若你更偏好 uWSGI,核心配置如下(二选一,不必同时装):
[uwsgi]
chdir = /opt/apps/myapp
module = app:app
master = true
processes = 4
threads = 2
socket = 127.0.0.1:8001
vacuum = true
die-on-term = true
logto = /var/log/myapp/uwsgi.log第三步:用 systemd 守护进程(推荐)
结论:systemd 是 Linux 自带的进程管理器,能实现开机自启、崩溃自动重启、日志统一收集,比 nohup 与 screen 可靠得多,也不需要额外安装组件。
创建 /etc/systemd/system/myapp.service:
[Unit]
Description=My Python Web App (Gunicorn)
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
User=www-data
Group=www-data
WorkingDirectory=/opt/apps/myapp
Environment="PATH=/opt/venvs/myapp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
EnvironmentFile=-/etc/myapp.env
ExecStart=/opt/venvs/myapp/bin/gunicorn -c /opt/apps/myapp/gunicorn.conf.py 'app:app'
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=30
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target敏感配置放进 /etc/myapp.env(注意权限设为 600):
sudo tee /etc/myapp.env <<'EOF'
FLASK_ENV=production
SECRET_KEY=改成随机长字符串
DATABASE_URL=mysql+pymysql://user:pass@127.0.0.1:3306/dbname
TZ=Asia/Shanghai
EOF
sudo chmod 600 /etc/myapp.env启用与日常管理:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
systemctl status myapp --no-pager
sudo systemctl restart myapp
sudo systemctl reload myapp # 触发 ExecReload,Gunicorn 平滑重载
journalctl -u myapp -f # 实时日志
journalctl -u myapp --since '1 hour ago' --no-pagerType=notify 需要 Gunicorn 安装时带 sdnotify(默认已支持);若启动报 Failed to read SERVICE_READY,把 Type 改成 simple 即可。
第四步:用 Supervisor 统一管理(可选)
结论:当你需要在一台机器上管理多个非系统级进程(Python 服务、队列消费者、Node 服务),Supervisor 提供了统一的控制面板与启停命令,比逐个写 systemd 单元更顺手。
sudo apt install -y supervisor
sudo systemctl enable --now supervisor创建 /etc/supervisor/conf.d/myapp.conf:
[program:myapp]
command=/opt/venvs/myapp/bin/gunicorn -c /opt/apps/myapp/gunicorn.conf.py app:app
directory=/opt/apps/myapp
user=www-data
autostart=true
autorestart=true
startsecs=10
startretries=3
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile=/var/log/myapp/supervisor.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=5
environment=PATH="/opt/venvs/myapp/bin",TZ="Asia/Shanghai"sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status
sudo supervisorctl restart myapp
sudo supervisorctl tail -f myapp # 看日志stopasgroup=true 与 killasgroup=true 很关键:Gunicorn 会 fork 子进程,不设这两项时停止主进程后子进程可能残留,导致端口占用。
第五步:配置 Nginx 反向代理
结论:Python 应用不直接对外,由 Nginx 处理静态文件、HTTPS、缓冲与限流,只把动态请求转发给 Gunicorn。
server {
listen 80;
server_name api.example.com;
client_max_body_size 20m;
location /static/ {
alias /opt/apps/myapp/static/; # 静态文件由 Nginx 直接返回
expires 30d;
access_log off;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 60s; # 应与 Gunicorn 的 timeout 相匹配
}
}sudo nginx -t && sudo systemctl reload nginx
curl -I http://127.0.0.1:8000 # 先确认应用本身能响应
curl -I https://api.example.com # 再确认代理链路
企业QQ咨询




