服务公告
Python-星耀云
发布时间:2026-04-27 18:01
搞过的人都知道,最烦的是Python环境问题:版本混乱、模块找不到、包装不上、编码报错,一套流程下来半天没了,代码还没开始写。本文汇总10年运维里见过最多的Python坑,手把手带你排掉。一、前言
Python部署环境问题比代码bug还恶心:本地跑得好好的服务器报错,pip装不上,ImportError一堆,版本切换乱套。本文解决:模块导入失败、依赖安装异常、多版本冲突、编码坑这四类高频问题。涉及CentOS/RHEL和Ubuntu不同路径时我会分开标注,别搞混。
二、操作步骤
第1步:确认Python版本和环境
# 先看系统里装了几个Python
$ which -a python python2 python3
/usr/bin/python
/usr/bin/python2.7
/usr/bin/python3.6
/usr/local/bin/python3.8
# 看具体版本号,2和3语法不兼容,混了要命
$ python --version
Python 2.7.18
$ python3 --version
Python 3.6.8
# 看pip对应哪个版本,装错地方模块就找不到
$ python -m pip --version
pip 21.0.1 from /usr/lib/python2.7/site-packages/pip (python 2.7)
$ python3 -m pip --version
pip 21.0.1 from /usr/lib/python3.6/site-packages/pip (python 3.6)预期输出:你会发现很多机器上pip和python版本不对应,比如python3装的模块python命令找不到。
第2步:处理ModuleNotFoundError
# 报错:ModuleNotFoundError: No module named 'requests'
# 先确认模块装在哪个Python里
$ python -c "import sys; print(sys.path)"
['', '/usr/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', ...]
$ python3 -c "import sys; print(sys.path)"
['', '/usr/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages', ...]
# 用pip3安装,装到python3的site-packages
$ python3 -m pip install requests
# 安装完后验证
$ python3 -c "import requests; print(requests.__version__)"
2.25.1预期输出:模块安装位置确认后,记住以后都要用 python3 -m pip 来操作,别裸用pip命令。
第3步:解决pip安装失败问题(网络/权限)
# 报错:pip install 超时或者权限拒绝
# 先试国内镜像,访问速度快
# CentOS/RHEL
$ python3 -m pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
# Ubuntu
$ sudo python3 -m pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
# 如果报权限错误(Read-only filesystem)
# 不要sudo,直接指定用户安装
$ python3 -m pip install --user requests
# 验证用户级安装路径
$ python3 -c "import site; print(site.getusersitepackages())"
/root/.local/lib/python3.6/site-packages
# 把这个路径加到PYTHONPATH
$ echo 'export PYTHONPATH=$PYTHONPATH:$(python3 -c "import site; print(site.getusersitepackages())")' >> ~/.bashrc
$ source ~/.bashrc预期输出:国内镜像秒装,用户级安装不依赖系统权限,生产环境推荐用--user。
第4步:创建和管理虚拟环境(venv)
# 项目依赖混乱?用venv隔离
# CentOS/RHEL默认可能没装venv,装一下
$ sudo yum install python3-venv -y
# 创建虚拟环境(Ubuntu自带python3-venv)
$ python3 -m venv /opt/myproject/env
# 激活虚拟环境
$ source /opt/myproject/env/bin/activate
# 激活后提示符变了,看这里
(env) [root@localhost ~]#
# 现在pip装的东西都在这个env里,跟系统隔离
(env) [root@localhost ~]$ pip list
Package Version
---------- -------
pip 21.0.1
setuptools 53.0.0
(env) [root@localhost ~]$ pip install requests flask
# 安装成功,现在这个项目的依赖全在env里
# 退出虚拟环境
(env) [root@localhost ~]$ deactivate预期输出:激活后pip list只有env里的包,系统包不受影响。搞完项目记得写requirements.txt。
第5步:导出和迁移依赖(requirements.txt)
# 在虚拟环境里导出当前依赖
(env) [root@localhost myproject]$ pip freeze > requirements.txt
# 查看文件内容
$ cat requirements.txt
certifi==2020.12.5
chardet==4.0.0
idna==2.10
requests==2.25.1
urllib3==1.26.4
# 新机器上一键安装
(env) [root@localhost newproject]$ pip install -r requirements.txt
# 也可以用pipreqs按实际导入生成,更精准
(env) [root@localhost myproject]$ pip install pipreqs
(env) [root@localhost myproject]$ pipreqs . --force
# 生成的是项目里真正用到的包,不带传递依赖预期输出:freeze会包含所有传递依赖,pipreqs只保留你代码import过的,文件更干净。
第6步:解决Python编码问题(UnicodeDecodeError)
# 报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbb
# 先看系统默认编码
$ python3 -c "import sys; print(sys.getdefaultencoding())"
utf-8
# 文件读写时指定编码
with open('test.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 如果文件是GBK编码的
with open('test.txt', 'r', encoding='gbk') as f:
content = f.read()
# 爬虫/请求回来的内容,先推断编码
import requests
r = requests.get('http://example.com')
r.encoding = r.apparent_encoding # 自动推断
print(r.text)
# 字符串和字节互转
s = "中文"
b = s.encode('utf-8') # str -> bytes
print(b) # b'\xe4\xb8\xad\xe6\x96\x87'
s2 = b.decode('utf-8') # bytes -> str
print(s2) # 中文预期输出:读文件永远指定encoding='utf-8',网络请求用apparent_encoding推断,别硬写编码名。
第7步:处理Python多版本共存切换(CentOS/RHEL)
# CentOS/RHEL默认python2,系统工具依赖它,别动
# 新项目全用python3,用update-alternatives管理
# 安装多个版本
$ sudo alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1
$ sudo alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.8 2
# 切换默认版本
$ sudo alternatives --set python3 /usr/bin/python3.6
# 或者
$ sudo alternatives --config python3
# 查看当前配置
$ alternatives --display python3
python3 - status is auto.
link currently points to /usr/local/bin/python3.8
/usr/bin/python3.6 - priority 1
/usr/local/bin/python3.8 - priority 2
# 切完后验证
$ python3 --version
Python 3.8.12预期输出:update-alternatives是CentOS/RHEL官方多版本管理方式,比改软链接安全,不影响yum/dnf。
第8步:处理Python多版本共存切换(Ubuntu)
# Ubuntu用update-alternatives一样的逻辑
$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1
$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2
$ sudo update-alternatives --config python3
There are 2 choices for the alternative python3 (providing /usr/bin/python3).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/python3.8 2 auto mode
1 /usr/bin/python3.6 1 manual mode
2 /usr/bin/python3.8 2 manual mode
Press <enter> to keep the default choice, or enter selection number:
# Ubuntu还有个更直接的方式:pyenv
$ curl https://pyenv.run | bash
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL
$ pyenv install 3.9.7
$ pyenv versions
system
3.6.8
3.9.7
# 进入目录自动切换版本
$ cd myproject
$ pyenv local 3.9.7
$ python --version
Python 3.9.7预期输出:Ubuntu下pyenv更省心,项目级版本隔离,不影响系统Python。
三、常见问题FAQ
Q1:pip install报SSL证书错误,链接被拒绝
老手吐槽:这个问题十有八九是公司内网或者代理搞的鬼,别上来就怪pip。
# 先看完整报错
$ python3 -m pip install requests
Collecting requests
Could not fetch URL https://pypi.org/simple/requests/: There was a problem confirming the ssl certificate
# 方法1:跳过SSL验证(临时用,不推荐生产环境)
$ python3 -m pip install requests --trusted-host pypi.org --trusted-host files.pythonhosted.org
# 方法2:装公司证书
$ sudo cp company_cert.crt /usr/local/share/ca-certificates/
$ sudo update-ca-certificates
# 方法3:设代理
$ export https_proxy=http://proxy.company.com:8080
$ python3 -m pip install requestsQ2:明明装了模块,但import还是报错
老手吐槽:这种情况80%是pip装到了别的Python版本里,先别骂娘,逐层排查。
# 第一步:看装在哪了
$ python3 -c "import sys; print(sys.executable)"
/usr/bin/python3
$ python3 -m pip show requests
Location: /usr/lib/python3.6/site-packages
# 第二步:检查sys.path里有没有这个路径
$ python3 -c "import sys; print('\n'.join(sys.path))"
# 第三步:直接看模块文件在不在
# CentOS/RHEL
$ ls /usr/lib/python3.6/site-packages/ | grep requests
requests-2.25.1.dist-info
# Ubuntu
$ ls /usr/local/lib/python3.6/dist-packages/ | grep requests
# 如果文件存在但还是报错,检查__init__.py有没有损坏
$ python3 -c "import requests; print(requests.__file__)"
/usr/lib/python3.6/site-packages/requests/__init__.py
# 文件路径有了还是报错,可能PYTHONPATH没包含这个目录
$ export PYTHONPATH=/usr/lib/python3.6/site-packages:$PYTHONPATHQ3:执行python脚本报错No such file or directory,但文件明明存在
老手吐槽:这坑新人必踩,是shebang行编码问题,别乱怀疑权限。
# 写了个脚本直接跑,报错
$ ./test.py
-bash: ./test.py: /usr/bin/python3: bad interpreter: No such file or directory
# 但文件确实存在
$ ls -la test.py
-rwxr-xr-x 1 root root 42 Jan 15 10:30 test.py
# 查看文件实际内容
$ cat -A test.py
^[[32m#!/usr/bin/python3^[[0m^M$
print("hello")
# ^M是Windows换行符\r,Linux不认
# 用dos2unix转换,或者sed直接删
$ sed -i 's/\r$//' test.py
# 再跑
$ ./test.py
helloQ4:virtualenv和venv用哪个
老手吐槽:Python3.3+自带venv,别再装virtualenv了,除非你要兼容Python2项目。
# Python3直接用venv
$ python3 -m venv myenv
$ source myenv/bin/activate
# 如果要用venv创建Python2环境(真的有必要吗?),装virtualenv
$ pip install virtualenv
$ virtualenv -p python2.7 py2env
# venv创建的环境不带pip,先装
$ python3 -m venv myenv
$ source myenv/bin/activate
$ curl https://bootstrap.pypa.io/get-pip.py | python四、总结
核心要点
- 版本第一:先确认python/python3/pip对应关系,搞混了后面全是坑
- pip永远用-m调用:python3 -m pip,别裸用pip命令
- 新项目必用虚拟环境:venv隔离依赖,不然依赖地狱等着你
- 文件读写指定encoding:utf-8是标准,别让系统猜
- Windows文件拷过来先查换行符:sed -i 's/\r$//' 是救命命令
- requirements.txt要进版本库:pip freeze是基础,pipreqs更精准
延伸阅读
- Python官方虚拟环境文档
- pip用户指南
- pyenv - Python版本管理
- 清华大学PyPI镜像
- 《Python Crash Course》第15章 - 环境配置相关
记住:Python环境问题都是配置问题,不是代码问题。先把环境搞干净,代码跑不起来再说别的。
相关推荐
上一篇: Docker-星耀云
已经是最后一篇啦!