Ubuntu 下发布 Python 应用,很多人一上来就找“通用命令”,结果很快卡在细节上。真正决定方案的,往往不是 Python 本身,而是你的程序到底要在线上提供服务,还是要交付成用户可直接运行的文件。下面就按这两种最常见的发布方式拆开讲:先看 Web 应用如何在生产环境落地,再看脚本和桌面程序怎样打包成可执行文件,同时把容易踩坑的地方一并说明白。
Web 应用上线:Flask / Django 的 Ubuntu 部署路径
如果你的项目是 Flask、Django 这类 Web 应用,发布的目标通常不是“生成一个文件”,而是让程序稳定运行在服务器上,对外提供 HTTP 服务。这个流程一般包括基础环境准备、代码上传、依赖安装、WSGI 运行和 Nginx 转发几步。

先把基础环境和虚拟环境准备好
Ubuntu 服务器上,Python 3、pip 和 git 基本属于必备组件,可以直接安装:
sudo apt update && sudo apt install python3 python3-pip git -y
接下来建议立刻创建虚拟环境。它的作用不是“可选优化”,而是隔离项目依赖,避免系统环境和其他项目的包版本互相冲突:
sudo apt install python3-venv -y
python3 -m venv myenv
source myenv/bin/activate
激活成功后,终端提示符会出现 (myenv),表示后续的 pip install、gunicorn 等操作都在这个隔离环境里执行。对于线上部署来说,这一步能减少大量“本地能跑、服务器报错”的问题。
上传代码并安装依赖
代码上传通常有两种方式。如果仓库已经放在 GitHub 或 Gitee,直接克隆最省事;如果项目还在本地机器上,也可以用 scp 传到服务器指定目录:
git clone https://github.com/your-username/your-webapp.git
# 或者
scp -r /local/path/to/project username@server_ip:/remote/path
上传完成后,依赖安装通常依靠 requirements.txt。这个文件可以在开发环境中通过下面的命令生成:
pip freeze > requirements.txt
到了服务器上,再统一安装:
pip install -r requirements.txt
这一步的意义,是把部署环境和开发环境尽量对齐。对于 Web 项目来说,依赖不一致是最常见的故障源之一,因此用 requirements.txt 固定依赖版本,往往比“临时手装几个包”更稳妥。
为什么生产环境要用 Gunicorn,再配 Nginx
很多初学者会直接用 Python 自带的开发服务器启动项目,但它只适合调试,不适合生产。正式上线时,通常要引入 WSGI 服务器,Gunicorn 是 Ubuntu 上非常常见的一种选择:
pip install gunicorn
gunicorn --bind 0.0.0.0:8000 app:app
这条命令的含义要看你的项目入口。例如入口文件是 app.py,Flask 应用对象叫 app,就写成 app:app;如果是 Django,常见对象名可能是 application。命令里绑定了 0.0.0.0:8000,表示监听 8000 端口并接受外部访问。
但 Gunicorn 通常不会直接面对公网请求。更常见的做法,是让 Nginx 充当前置反向代理:负责接收 HTTP 请求,再转发给本机的 Gunicorn 进程。
sudo apt install nginx -y
sudo nano /etc/nginx/sites-a vailable/yourapp
配置内容可以类似下面这样:
server {
listen 80;
server_name your_domain_or_ip;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
这段配置的重点是:Nginx 对外监听 80 端口,收到请求后转发到本机 127.0.0.1:8000,也就是 Gunicorn 所在的位置,同时保留主机头和客户端真实 IP 等信息。
配置完成后,再启用站点并重启 Nginx:
sudo ln -s /etc/nginx/sites-a vailable/yourapp /etc/nginx/sites-enabled/
sudo systemctl restart nginx
严格来说,原文里的目录名写成了 sites-a vailable,实际操作时应确认路径是否正确,否则软链接和配置文件都可能找不到。思路不变:Gunicorn 负责跑 Python,Nginx 负责对外接流量,这才是更接近生产环境的组合。
用 systemd 做开机自启,避免服务重启后失联
如果服务器重启后应用不能自动恢复,线上服务就会直接中断,所以部署完成后通常还会补上一层 systemd 服务管理。先创建服务文件:
sudo nano /etc/systemd/system/my_python_service.service
服务内容可以写成这样:
[Unit]
Description=My Python Web Application
After=network.target
[Service]
User=your_username
ExecStart=/path/to/your/venv/bin/gunicorn --bind 0.0.0.0:8000 app:app
Restart=always
[Install]
WantedBy=multi-user.target
然后启用并启动服务:
sudo systemctl enable my_python_service
sudo systemctl start my_python_service
这里最关键的是 ExecStart。它必须明确指向虚拟环境中的 Gunicorn 绝对路径,否则 systemd 很容易调用到系统环境下的可执行文件,进而出现模块缺失、版本不匹配或服务启动失败的问题。对于部署稳定性来说,这个细节比命令本身更重要。
桌面程序或脚本交付:打包成可执行文件
如果你的目标不是上线一个 Web 服务,而是把 Python 脚本交给别人直接运行,那么发布方式就完全不同了。这类场景关注的是“目标机器上不装 Python 也能跑”,因此需要使用打包工具把解释器和依赖一起封装。

PyInstaller:上手最快的常见方案
PyInstaller 是使用最广的 Python 打包工具之一,优点就是简单直接。先安装工具:
pip install pyinstaller
然后执行打包命令:
pyinstaller --onefile your_script.py
--onefile 的意思是把程序打成单个可执行文件。如果不加这个参数,通常会生成一个包含主程序和依赖文件的目录结构。打包结束后,产物会出现在 dist/ 目录中:在 Linux 下通常没有后缀,在 Windows 下则会生成 .exe。
如果你的需求是快速分发一个单脚本工具,PyInstaller 往往是优先级最高的选择,因为命令少、学习成本低,适合先验证能不能交付,再根据结果处理资源文件或兼容性问题。
cx_Freeze:项目结构更复杂时的另一种选择
当项目结构更复杂,或者你希望通过配置文件更细致地控制打包内容时,cx_Freeze 也值得考虑。安装方式如下:
pip install cx_Freeze
接着在项目根目录创建 setup.py:
from cx_Freeze import setup, Executable
setup(
name="YourApp",
version="0.1",
description="Your application description",
options={
"build_exe": {
"packages": ["os"],
"excludes": ["tkinter"]
}
},
executables=[Executable("your_script.py")]
)
然后执行构建:
python setup.py build
生成结果位于 build/ 目录。和 PyInstaller 相比,cx_Freeze 更适合那些需要明确声明包、排除不必要模块、对构建过程有更多控制要求的项目。换句话说,PyInstaller 适合快速成包,cx_Freeze 更像是面向复杂项目的配置化方案。
发布前最值得确认的三个问题
无论你走的是服务器部署,还是桌面打包,最后都建议回头检查几个容易忽略、但会直接影响交付结果的问题。
1. 跨平台不是自动成立的
这是最容易被误判的一点。打包后的可执行文件通常只能运行在当前打包时所处的操作系统上。也就是说,你在 Ubuntu 上打出来的文件,不能直接拿到 Windows 上运行;反过来也是一样。如果目标用户在不同平台上使用,就需要分别在对应平台完成打包。
2. 资源文件必须显式带上
如果项目依赖图片、配置文件或其他静态资源,只打包主脚本通常不够。以 PyInstaller 为例,可以通过 --add-data 参数把资源一起打进去:
pyinstaller --add-data "config.ini:."
这里的关键不是命令格式本身,而是要意识到:代码能启动,不代表运行过程中读到的外部文件也已经被正确带上。很多“打包成功但程序打不开配置”的问题,都是出在这里。
3. 依赖要在打包前先查全
无论使用哪种打包工具,都默认你的环境里已经装好了程序所需依赖。它不会替你推断所有遗漏的第三方包,因此在打包前确认虚拟环境是否完整非常重要。否则即使成功生成了文件,用户运行时仍可能遇到模块缺失、启动失败或部分功能不可用的情况。
把这三点和前面的流程串起来看,Ubuntu 下发布 Python 应用其实并不复杂,关键在于先判断应用类型,再选对交付路径。Web 项目重在服务进程、反向代理和自启动;脚本或桌面程序重在打包工具、资源文件和目标平台一致性。只要这条判断线清楚,很多看似零散的命令就能自然归位。









