1. 装之前先想清楚:你到底需要什么
CentOS 7上装Python和Jupyter,是我这些年被问得最多的服务器配置问题。原因很直接:CentOS 7系统自带的Python还是2.7.5,早就跟不上时代了,但现在大量数据分析、爬虫、自动化脚本都在Python 3上跑,加上Jupyter Notebook作为远程交互式编程入口又特别好用,所以几乎每个和数据沾边的项目交付时,都绕不开这一套组合。
这篇文章就把我从零开始装一套的完整过程拆给你看:怎么编译安装Python 3,怎么用虚拟环境装Jupyter,怎么配置远程访问,以及我踩过的坑和排查思路。适合刚拿到一台CentOS 7服务器、想在上面跑Python和Jupyter Notebook的同学直接照着操作。
先说结论:在CentOS 7上装Python,最稳的方式是源码编译安装,不建议直接改系统自带的Python 2.7——那个版本是yum等系统工具的依赖,动它等于拆家。下面从环境准备开始,一步步往下走。
1.1 为什么系统自带的Python 2.7不能轻易动
CentOS 7默认的Python版本是2.7.5,这个版本挂在系统底层,yum、firewalld、selinux的很多管理工具都是基于它的。如果你手贱把/usr/bin/python指向了Python 3,轻则yum报错,重则系统管理命令失灵,我就见过有人这么干完连yum install都跑不了。
所以装新Python的正解是:保留系统Python 2.7,单独装一个Python 3到独立目录,两份并存。系统工具继续走Python 2.7,我们自己的项目走Python 3,互不干扰。这也是下面所有操作的基本逻辑。
1.2 版本怎么选
Python版本不是越新越好,我推荐用Python 3.9或3.10。原因很实际:
- 3.8以下的版本官方支持已经陆续到期,安全补丁不更新了,别用。
- 3.11、3.12虽然新,但很多第三方库(尤其是一些科学计算、国产软件SDK的二进制包)还没完全适配,你在pip install的时候会遇到"没有匹配的wheel"之类的报错。
- 3.9、3.10处于生态兼容的"甜点区",主流库全覆盖,企业项目用得最多,遇到问题也容易搜到答案。
以我这次的操作举例,我用的是Python 3.9.18,稳定、兼容性好,Jupyter全家桶和pandas、numpy这些核心库全都完美支持。
1.3 三种安装方式怎么选
在CentOS 7上装Python 3,主流的路线有三条,我直接做了个对比:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 源码编译 | 版本自由选、目录自己控制、最稳 | 耗时长(约10-20分钟)、依赖要装齐 | 生产服务器、长期使用 |
| yum/SCL安装 | 命令简单、不用编译 | 版本陈旧、SCL还需额外配置环境 | 只想要新版本临时用 |
| Miniconda安装 | 自带Python和环境管理、装数据科学库方便 | 包体积大、文件位置和系统风格割裂 | 纯数据分析用户 |
我个人的建议是:如果你主要玩数据分析和Jupyter,用Miniconda可能更省心;但如果你是想让这台服务器长期跑Python服务,或者你希望完全掌控Python安装位置,就老老实实源码编译。我这篇主教程以源码编译为主,因为它的通用性和可控性最好,过程搞明白了,其他方式都是小菜。
2. 环境准备:先让服务器"活过来"
很多人装到一半失败,其实不是Python的问题,而是服务器环境本身就没准备好。新拿到的CentOS 7服务器,一般有两个绕不开的坎:网络可能不通、yum源可能不好用。先把这两个解决掉,后面才顺。
2.1 网络和基础检查
拿到服务器后,第一件事不是急着下Python,而是确认网络能用。我习惯先跑几条命令:
ip addr ip route cat /etc/resolv.conf分别看IP、网关和DNS配置。新装的CentOS 7经常出现有IP但ping不通外网的情况,比如ping www.baidu.com报unknown host,但ping 114.114.114.114却是通的——这说明DNS配置有问题。
DNS问题比较好修,编辑/etc/resolv.conf,加上有效的DNS服务器就行:
nameserver 223.5.5.5 nameserver 114.114.114.114如果网关不对,就得检查/etc/sysconfig/network-scripts/ifcfg-eth0这类网卡配置文件,确保GATEWAY和DNS字段正确。修改后执行systemctl restart network重启网络服务。这些基础问题不搞定,后面wget源码、pip装包都会折磨你。
2.2 换一个能用的yum源
CentOS 7的官方源在国内访问经常很慢或者直接超时。我的习惯是一到手就换成国内镜像源,这一步能省下大量等待时间。
操作方式是先备份原来源配置:
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak然后下载国内镜像的repo文件。以阿里云源为例:
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo下载完成后清理缓存:
yum clean all yum makecache后面再用yum install装依赖的时候,速度快得不是一点半点。这里提醒一句:改完源以后,如果yum还是报错,多半是repo文件里的版本号或路径不匹配,检查一下baseurl里的路径是否存在。
2.3 安装编译Python必需的依赖
源码编译Python之前,工具链和开发库必须装齐,否则后面make阶段会出现各种诡异的报错,比如缺zlib导致无法安装pip、缺openssl导致pip install连不上HTTPS源。
我每次都会执行这一整条命令:
yum install -y gcc gcc-c++ make wget perl \ zlib-devel bzip2-devel libffi-devel \ openssl-devel readline-devel sqlite-devel \ tk-devel gdbm-devel xz-devel逐个说下这些包是干嘛的:
gcc和gcc-c++是编译源码必需的编译器。zlib-devel:Python压缩模块zlib依赖它,不装的话pip都起不来。openssl-devel:让Python支持HTTPS,装了它pip install才能访问外网源。libffi-devel:ctypes模块需要它,很多扩展库都会用到。readline-devel:装Python交互式界面时上下翻历史命令才正常。sqlite-devel:Python自带的sqlite3模块依赖它,Jupyter的很多元数据存储也会用到。
这些依赖建议一次性装齐,别等编译报错了再回头补。我帮人排查过太多次"编译到一半提示缺头文件"的情况,基本都是这一步没做好。
3. 源码编译安装Python 3.9
到这一步,环境已经清爽了。现在正式编译安装Python。
3.1 下载源码包并解压
源码包可以从官方python.org下载,也可以走国内镜像站,速度会快一些。我直接用的官方地址:
cd /usr/local/src wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz tar -xvf Python-3.9.18.tgz cd Python-3.9.18下载前可以先看一眼这个路径是否存在,如果官方路径调整了,就去https://www.python.org/ftp/python/目录下找对应版本号。
3.2 configure配置:关键参数要明白
解压之后,编译前先做配置。这一步决定了Python安装到哪个目录、启用哪些功能:
./configure --prefix=/usr/local/python3.9 --enable-optimizations --with-ssl几个关键参数我说一下:
--prefix=/usr/local/python3.9:指定安装目录。这样所有文件都集中在/usr/local/python3.9,不污染系统目录,以后想卸载直接删这个目录就行。--enable-optimizations:开启编译优化,会用profile-guided optimization方式编译,性能更好,但会让编译时间明显变长。如果机器性能一般,可以先不加这个参数。--with-ssl:确保SSL模块编译进来,没有它后面pip走HTTPS会集体报错。
配置完成后,编译过程还有额外依赖,比如_tkinter模块需要tk-devel,这些在前面已经装过了。如果configure阶段卡住,屏幕上的错误信息会明明白白告诉你缺少什么,照着提示去yum install对应的-devel包就行。
3.3 make编译:内存小有对策
接下来是编译本体:
make -j2-j2表示用2个核心并行编译。如果你的服务器核数多,可以调成make -j4甚至make -j$(nproc),速度会快不少。但要注意:并行数开太高,内存小的机器容易编译期被OOM杀掉。我曾在只有1G内存的机器上开-j4,结果编译到一半直接卡死,后来降到-j1才顺利过。
编译过程5到15分钟不等,取决于机器性能。编译完以后安装:
make install安装完成后,验证一下:
/usr/local/python3.9/bin/python3 --version如果输出Python 3.9.18,说明安装成功。还没完,得把这个Python暴露到命令行里,不然每次都要写一长串路径。
3.4 建立软链接,和系统Python共存
这里要特别小心,千万不能把/usr/bin/python改掉。正确的做法是创建一个单独的链接,比如:
ln -s /usr/local/python3.9/bin/python3 /usr/bin/python3 ln -s /usr/local/python3.9/bin/pip3 /usr/bin/pip3这样做的效果是:系统原有的python2和python都不受影响,而新环境里敲python3和pip3就能直接用新版。如果你还想让python这个命令直接指向Python 3,我建议只在当前用户的PATH里做手脚,别动系统级链接。
用户级别的做法是在~/.bashrc里加一行:
export PATH=/usr/local/python3.9/bin:$PATH然后source ~/.bashrc。这样你这个用户登进去敲python3就是3.9.18,而系统工具依然走原来的Python 2.7,两边相安无事。
4. 用虚拟环境安装Jupyter Notebook
Python装好之后,下一步是装Jupyter。这里我强烈推荐先建一个虚拟环境,不要直接把Jupyter装进全局Python里。为什么?因为Python项目之间的依赖经常互相打架,今天这个项目要A版本,明天那个项目要B版本,全装在一起迟早出事。虚拟环境就是给每个项目一个独立的小房间。
4.1 创建并激活虚拟环境
用Python 3自带的venv模块就能建虚拟环境:
cd /opt /usr/local/python3.9/bin/python3 -m venv jupyter_env source /opt/jupyter_env/bin/activate激活之后,命令行提示符前面会出现(jupyter_env),这时候你敲python3和pip3用的都是虚拟环境里的版本,不会污染全局。这种隔离方式是我在所有服务器上的标准做法,简单可靠,不用额外装任何东西。
4.2 安装Jupyter Notebook和JupyterLab
在激活的虚拟环境里,直接pip安装:
pip install --upgrade pip pip install jupyter notebook jupyterlab这里有两个选择:notebook是经典版本,界面朴素但稳定;jupyterlab是新一代界面,功能更强、更现代。我个人建议两个都装,日常用Lab,兼容老教程时用Notebook。
安装过程可能会有点慢,因为Jupyter的依赖包非常多。如果等得不耐烦,可以配置pip走国内镜像源。修改~/.pip/pip.conf:
[global] index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com配置好以后,再装就快多了。
4.3 配置远程访问:IP、端口、密码
Jupyter装完,如果没有配置文件,默认只监听localhost,你在本地浏览器是访问不到服务器上的Jupyter的。所以必须做远程访问配置。
先生成配置文件:
jupyter notebook --generate-config然后设置登录密码。现在的Jupyter推荐用哈希密码,我们用ipython来生成:
python3 -c "from notebook.auth import passwd; print(passwd())"按提示输入两遍密码,会得到一串argon2:...格式的哈希值,记下来。
接下来编辑配置文件,一般路径是~/.jupyter/jupyter_notebook_config.py,把下面几行加进去或改掉:
c.ServerApp.ip = '0.0.0.0' c.ServerApp.port = 8888 c.ServerApp.password = 'argon2:刚才生成的哈希值' c.ServerApp.open_browser = False c.ServerApp.allow_root = True简单解释一下:
ip='0.0.0.0':让Jupyter监听所有网卡,这样局域网或远程才能访问。port=8888:默认端口,如果想换就换。password:用刚才生成的哈希密码,不是明文。open_browser=False:服务器上没有浏览器,防止启动时报错。allow_root=True:如果你是root用户,不设这个Jupyter会直接拒绝启动。
4.4 防火墙放行端口
配置好之后,先要确认防火墙没有挡住8888端口。CentOS 7默认用firewalld:
firewall-cmd --zone=public --add-port=8888/tcp --permanent firewall-cmd --reload如果你用的是云服务器,还要去云控制台的安全组里放行8888端口。这一步被无数人忽略,结果本地明明配好了,外面就是访问不了。
5. 启动Jupyter和日常使用实战
配置完成,现在可以启动Jupyter了。但在启动方式上,我吃过不少亏,分享一下我现在最推荐的几种做法。
5.1 不要裸启动,用systemd托管
很多初学者喜欢直接敲jupyter notebook,然后开一个终端窗口挂着,这样做有个致命的坑:SSH一断开,Jupyter就死了。等你第二天回来访问,发现服务没了,一脸懵。
正确做法是用nohup后台运行,或者写一个systemd服务让它开机自启。先看简单的nohup方式:
nohup /opt/jupyter_env/bin/jupyter notebook --config=/root/.jupyter/jupyter_notebook_config.py > /var/log/jupyter.log 2>&1 &这样即使SSH断开,进程也还活着,日志写在/var/log/jupyter.log里方便排查。
不过我更推荐直接用systemd管理。创建一个服务文件/etc/systemd/system/jupyter.service:
[Unit] Description=Jupyter Notebook Server After=network.target [Service] Type=simple User=root Environment="PATH=/opt/jupyter_env/bin:/usr/local/python3.9/bin:/usr/bin" ExecStart=/opt/jupyter_env/bin/jupyter notebook --config=/root/.jupyter/jupyter_notebook_config.py Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target然后启用并启动:
systemctl daemon-reload systemctl enable jupyter systemctl start jupyter这个方案的好处是:开机自动启动,挂了自动重启,日志通过journalctl -u jupyter就能看。我在生产服务器上全部采用这种方式,极其省心。
5.2 怎么看服务状态和日志
如果服务起不来,第一反应是看状态和日志:
systemctl status jupyter journalctl -u jupyter -n 50 --no-pager日志里通常会有明确的报错——端口被占、配置文件路径不对、密码哈希格式不支持,基本都能直接定位。比如我看到过的几个高频报错:
Permission denied:配置文件或日志目录没权限,检查权限或者User字段。Address already in use:8888端口已经被占用,改端口或者杀掉旧进程。Unknown error opening terminal:这类少见于纯净CentOS,一般是环境变量被搞乱,重新登录就好。
5.3 怎么让Jupyter默认打开指定目录
很多人问"Jupyter怎么创建在别的文件夹",其实只要在配置里指定根目录就行。在jupyter_notebook_config.py中设置:
c.ServerApp.root_dir = '/data/notebooks'这里root_dir和老的notebook_dir是一个意思,新版Jupyter的配置项换成了root_dir。设置好后,Jupyter网页版的文件浏览器就固定在这个目录下,新建的.ipynb也都存在这里。
如果只是想临时用,也可以在启动命令后面加参数:
jupyter notebook --notebook-dir=/data/notebooks5.4 同时挂多个Python环境的Kernel
在实战中,你可能会遇到多个项目、多个虚拟环境的情况。Jupyter默认只显示启动它时的那个Python环境,要让它认识其他环境,需要装ipykernel并把环境注册进去。比如我已经有了另一个环境/opt/project_venv,就这么操作:
source /opt/project_venv/bin/activate pip install ipykernel python3 -m ipykernel install --name project_env --display-name "Python (project_env)" deactivate刷新Jupyter页面后,新建Notebook的内核选择列表里就会出现"Python (project_env)"。这是管理多环境Jupyter的必备技巧,我强烈推荐给经常切换项目的朋友。
6. 常见问题排查实录
这部分是我做运维多年最想分享的内容。装Jupyter本身不难,难的是出了问题不知道怎么排。我把热搜词里大家最关心的问题聚拢一下,按我实际的工作顺序写出来,希望能帮你少走弯路。
6.1 yum没法用了:Could not resolve host / baseurl失效
yum install报Could not resolve host: mirror.xxx.com,十有八九是DNS问题,按我在2.1里的方法先检查/etc/resolv.conf。
还有一种情况是报Cannot find a valid baseurl for repo,这通常是因为CentOS 7官方源已经停止维护,或者repo文件里的路径失效了。处理方式就是2.2说的:换一个可用的镜像源,并确认repo文件里的baseurl能正常访问。这里多一句嘴:如果你自己改了repo文件导致yum崩了,恢复配置最直接的方式是把备份的CentOS-Base.repo.bak改回去。
6.2 ping不通百度但IP通,怎么回事
热搜词里"centos7 无法ping通百度"这个场景,我几乎每周都见。现象很典型:
ping www.baidu.com # 报 ping: unknown host ping 114.114.114.114 # 正常通这说明网络链路没问题,就是DNS解析失败。解决思路很简单:确认/etc/resolv.conf里的nameserver没有被清掉,或者换一个公共DNS。改完立刻测试,不用重启网卡。如果改了还是不行,检查网卡配置里是否有PEERDNS=no之类的设置,它可能阻止DHCP更新DNS。
6.3 pip明明装了却提示找不到命令
装完Python后敲pip3提示command not found,通常有几种原因:
- 安装目录的bin目录没有加入PATH。通过
export PATH=/usr/local/python3.9/bin:$PATH解决。 - 某些情况下,安装完没有执行
source ~/.bashrc。因为nohup、编译安装等操作,当前shell的PATH没有刷新,hash -r清一下缓存就好。 - 虚拟环境激活失败,你人在虚拟环境之外,自然用的是系统pip。
排查命令就一条,先看Python在哪:
which python3 which pip36.4 Jupyter启动时报"找不到指定的程序"
这个报错在Windows上出现得多,但在Linux服务器上也偶尔能看到类似的现象。根本原因就一个字:路径错乱。
比如,你明明进入了虚拟环境,但启动的还是全局的jupyter;或者虚拟环境里的jupyter脚本指向了不存在的Python解释器。解决办法是确保用的是虚拟环境里的程序:
which jupyter看输出的路径是否在虚拟环境目录下。如果不是,先确认你激活了虚拟环境;如果虚拟环境坏了,重建一个最省事——我经历过太多次修复半天不如重来快。
另一种情况是启动时报缺少模块,比如ModuleNotFoundError: No module named 'notebook',这说明Jupyter安装不完整,用pip install --force-reinstall jupyter notebook重装一遍。
6.5 配置了远程访问,还是打不开网页
这算是远程配置里最常翻车的一环。按优先级排查:
- Jupyter是否监听了
0.0.0.0,用netstat -tlnp | grep 8888看监听地址。只显示127.0.0.1:8888就是配置没生效,改完配置记得重启服务。 - 防火墙是否放行,按4.4检查。
- 云服务器安全组是否放行8888端口,这个很多人忘记,本地测试通就以为是正常的。
- 浏览器访问时地址是不是写对了,
http://服务器IP:8888,不是https。
6.6 网页能打开,但执行代码很卡
这个问题很多人会忽略,其实Jupyter对内存要求比想象中高。服务器如果只有1G或2G内存,开几个大DataFrame基本就卡死。
解决办法有两步:
第一步,设置swap。在低内存机器上,给个2G的swap能明显缓解:
fallocate -l 2G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile同时写入/etc/fstab使其开机自动挂载。
第二步,合理设置Jupyter的资源使用方式,比如不要一个浏览器开几十个cell疯狂运行,大任务尽量写成.py脚本后台跑,别在Notebook里裸奔。
6.7 Notebook一个cell只显示最后一行输出
有朋友问"Jupyter一个cell只输出最后一行为什么",这是Notebook的默认行为——如果cell里有多个变量或表达式,只有最后一行会作为output显示。解决办法是显式使用print(),或者用IPython.display.display()来展示多个结果。
from IPython.display import display display(df1) display(df2)这在数据分析时特别实用,可以同时看多个表的概况,不用来回改代码。
最后再分享一个我个人的习惯:安装完Jupyter以后,我会马上把系统做一次快照或镜像,这样以后环境坏了,直接回滚比重新配置快太多。服务器上的Python/Jupyter环境一辈子也就搭那么一两次,但每次搭都值得留个备份。加上systemd托管之后,这套环境基本能做到长期安稳运行,你只需要把精力放在写代码本身,而不是反复折腾环境。