Python:本地虚拟环境的搭建

为什么要在本地创建虚拟环境

个人经历

我在刚学Python的时候,并没有创建虚拟环境。所有包都是全局下载。

可当我需要把Python代码部署到服务器的时候,问题就出现了。

因为在服务器上,我们也需要运行pip或者conda来下载项目中所使用的包。

那么如何知道项目中使用了哪些包呢?

可以运行如下命令:

# pip的命令
pip freeze > requirements.txt

# conda的命令
conda env export > environment.yml

把这个项目中使用到的包信息都放在requirements.txt或者environment.yml

我得到的environment.yml文件内容如下

name: base
channels:
  - conda-forge
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
dependencies:
  - anaconda-anon-usage=0.5.0=py312hfb7c958_100
  - annotated-types=0.6.0=py312hecd8cb5_0
  - archspec=0.2.3=pyhd3eb1b0_0
  - asgiref=3.8.1=pyhd8ed1ab_1
  - black=24.10.0=py312hecd8cb5_0
  - blas=1.0=openblas
  - boltons=24.1.0=py312hecd8cb5_0
  - bottleneck=1.4.2=py312ha2b695f_0
  - brotli-python=1.0.9=py312h6d0c2b6_9
  - bzip2=1.0.8=h6c40b1e_6
  - c-ares=1.19.1=h6c40b1e_0
  - ca-certificates=2025.4.26=hbd8a1cb_0
  - certifi=2025.4.26=py312hecd8cb5_0
  - cffi=1.17.1=py312h9205ec4_1
  - charset-normalizer=3.3.2=pyhd3eb1b0_0
  - click=8.1.8=py312hecd8cb5_0
  - conda=25.3.1=py312hecd8cb5_0
  - conda-anaconda-telemetry=0.1.2=py312hecd8cb5_0
  - conda-anaconda-tos=0.1.2=py312hecd8cb5_0
  - conda-content-trust=0.2.0=py312hecd8cb5_1
  - conda-libmamba-solver=25.1.1=pyhd3eb1b0_0
  - conda-package-handling=2.4.0=py312hecd8cb5_0
  - conda-package-streaming=0.11.0=py312hecd8cb5_0
  - contourpy=1.3.1=py312h1962661_0
  - cpp-expected=1.1.0=h1962661_0
  - cryptography=43.0.3=py312he15b966_1
  - cycler=0.11.0=pyhd3eb1b0_0
  - distro=1.9.0=py312hecd8cb5_0
  - django=5.1.3=py312hecd8cb5_0
  - djhtml=3.0.7=pyhd8ed1ab_0
  - expat=2.6.4=h6d0c2b6_0
  - fmt=9.1.0=ha357a0b_1
  - fonttools=4.55.3=py312h46256e1_0
  - freetype=2.13.3=h02243ff_0
  - frozendict=2.4.2=py312hecd8cb5_0
  - icu=73.1=hcec6c5f_0
  - idna=3.7=py312hecd8cb5_0
  - jpeg=9e=h46256e1_3
  - jsonpatch=1.33=py312hecd8cb5_1
  - jsonpointer=2.1=pyhd3eb1b0_0
  - kiwisolver=1.4.8=py312h6d0c2b6_0
  - krb5=1.20.1=h428f121_1
  - lcms2=2.16=h4f63f0c_0
  - lerc=4.0.0=h6d0c2b6_0
  - libarchive=3.7.7=h4c66a04_0
  - libcurl=8.11.1=h9bcc28a_0
  - libcxx=14.0.6=h9765a3e_0
  - libdeflate=1.22=h46256e1_0
  - libedit=3.1.20230828=h6c40b1e_0
  - libev=4.33=h9ed2024_1
  - libffi=3.4.4=hecd8cb5_1
  - libgfortran=5.0.0=11_3_0_hecd8cb5_28
  - libgfortran5=11.3.0=h9dfd629_28
  - libiconv=1.16=h6c40b1e_3
  - libmamba=2.0.5=hfd235c6_1
  - libmambapy=2.0.5=py312h1962661_1
  - libnghttp2=1.57.0=h9beae6a_0
  - libopenblas=0.3.29=h3f8574a_0
  - libpng=1.6.39=h6c40b1e_0
  - libsolv=0.7.30=h2761308_1
  - libssh2=1.11.1=h3a17b82_0
  - libtiff=4.5.1=h6fa9cd1_1
  - libwebp-base=1.3.2=h46256e1_1
  - libxml2=2.13.5=h6070cd6_0
  - llvm-openmp=14.0.6=h0dcd299_0
  - lz4-c=1.9.4=hcec6c5f_1
  - markdown=3.8=py312hecd8cb5_0
  - markdown-it-py=2.2.0=py312hecd8cb5_1
  - matplotlib=3.10.0=py312hecd8cb5_0
  - matplotlib-base=3.10.0=py312h919b35b_0
  - mdurl=0.1.0=py312hecd8cb5_0
  - menuinst=2.2.0=py312hecd8cb5_1
  - mypy_extensions=1.0.0=py312hecd8cb5_0
  - ncurses=6.4=hcec6c5f_0
  - nlohmann_json=3.11.2=hcec6c5f_0
  - numexpr=2.10.1=py312hc59c7be_0
  - numpy=2.0.1=py312h255ab90_1
  - numpy-base=2.0.1=py312h12d8432_1
  - openjpeg=2.5.2=hbf2204d_0
  - openssl=3.5.0=hc426f3f_1
  - packaging=24.2=py312hecd8cb5_0
  - pandas=2.2.3=py312h6d0c2b6_0
  - pathspec=0.10.3=py312hecd8cb5_0
  - pcre2=10.42=h9b97e30_1
  - pillow=11.1.0=py312h47bf62f_0
  - pip=25.0=py312hecd8cb5_0
  - platformdirs=3.10.0=py312hecd8cb5_0
  - pluggy=1.5.0=py312hecd8cb5_0
  - pybind11-abi=5=hd3eb1b0_0
  - pycosat=0.6.6=py312h46256e1_2
  - pycparser=2.21=pyhd3eb1b0_0
  - pydantic=2.10.3=py312hecd8cb5_0
  - pydantic-core=2.27.1=py312h83de92b_0
  - pygments=2.19.1=py312hecd8cb5_0
  - pymysql=1.1.1=pyhd8ed1ab_1
  - pyparsing=3.2.0=py312hecd8cb5_0
  - pypinyin=0.54.0=pyhd8ed1ab_0
  - pysocks=1.7.1=py312hecd8cb5_0
  - python=3.12.9=hcd54a6c_0
  - python-dateutil=2.9.0post0=py312hecd8cb5_2
  - python-tzdata=2025.2=pyhd3eb1b0_0
  - python.app=3=py312h46256e1_1
  - pytz=2024.1=py312hecd8cb5_0
  - pyyaml=6.0.2=py312h46256e1_0
  - readline=8.2=hca72f7f_0
  - reproc=14.2.4=hcec6c5f_2
  - reproc-cpp=14.2.4=hcec6c5f_2
  - requests=2.32.3=py312hecd8cb5_1
  - rich=13.9.4=py312hecd8cb5_0
  - ruamel.yaml=0.18.6=py312h46256e1_0
  - ruamel.yaml.clib=0.2.8=py312h46256e1_0
  - setuptools=75.8.0=py312hecd8cb5_0
  - simdjson=3.10.1=h1962661_0
  - six=1.17.0=py312hecd8cb5_0
  - spdlog=1.11.0=ha357a0b_0
  - sqlite=3.45.3=h6c40b1e_0
  - sqlparse=0.5.3=pyhd8ed1ab_0
  - tk=8.6.14=h4d00af3_0
  - tornado=6.4.2=py312h46256e1_0
  - tqdm=4.67.1=py312h8e4b320_0
  - truststore=0.10.0=py312hecd8cb5_0
  - typing-extensions=4.12.2=py312hecd8cb5_0
  - typing_extensions=4.12.2=py312hecd8cb5_0
  - tzdata=2025a=h04d1e81_0
  - unicodedata2=15.1.0=py312h46256e1_1
  - urllib3=2.3.0=py312hecd8cb5_0
  - wheel=0.45.1=py312hecd8cb5_0
  - xz=5.4.6=h6c40b1e_1
  - yaml=0.2.5=haf1e3a3_0
  - yaml-cpp=0.8.0=hcec6c5f_1
  - zlib=1.2.13=h4b97444_1
  - zstandard=0.23.0=py312h5bcdf72_1
  - zstd=1.5.6=h138b38a_0
prefix: /opt/miniconda3

里面的内容非常多。这是因为我没有配置虚拟环境,命令会把我所有的包都下载下来。有很多的包是我在上一个项目用到但是在这个项目中没有用到的,比如numpymatplotlib

因此,我们需要创建虚拟环境,做好项目隔离。

创建虚拟环境的好处

项目依赖隔离

  • 不同的 Python 项目可能需要不同版本的库(如 numpydjango 等),甚至不同版本的 Python 解释器。
  • 虚拟环境允许每个项目拥有独立的依赖库,避免全局安装(pip install)导致的版本冲突问题。

便于依赖管理

  • 虚拟环境可以配合 requirements.txtpipenv/poetry 等工具记录项目依赖,方便团队协作或部署。

    pip freeze > requirements.txt  # 导出依赖
    pip install -r requirements.txt  # 重新安装依赖
    

支持多 Python 版本

  • 如果机器上安装了多个 Python 版本(如 Python 3.7 和 3.10),可以为每个项目指定不同的 Python 解释器:

    python3.7 -m venv myenv  # 使用 Python 3.7 创建虚拟环境
    

简化部署与移植

  • 虚拟环境的所有依赖都集中在项目目录中(如 venv/ 文件夹),便于打包或复制到其他环境运行。

如何创建本地虚拟环境

三种方式创建虚拟环境

方法 常用命令 底层机制 是否依赖 Conda 适用场景
python python -m venv myenv 标准库 venv 模块 轻量项目、纯 Python 环境
pip pip install virtualenv + virtualenv myenv virtualenv 第三方包 对旧版本 Python 或多版本管理更灵活
conda conda create -n myenv python=3.10 Conda 虚拟环境系统 科研、需要科学库或跨平台兼容
  • 注意:这里的pip实际上是不能创建虚拟环境的,是要通过virtualenv 第三方包

使用建议总结:

场景 推荐方式
Web 后端、轻量开发 python -m venv
多版本 Python 项目 virtualenv
数据分析 / AI / 科研项目 conda create

为什么不推荐使用 Conda 来做 Web 项目虚拟环境?

问题 原因
🔧 环境过重 Conda 虚拟环境大(几百 MB 起),打包部署不方便
🚫 PyPI 兼容性问题 Conda 安装包并不总是最新,有些库(如某些 Django 扩展)只能用 pip 安装
🐳 Docker 部署复杂 Conda Docker 镜像比 venv 的镜像大很多,CI/CD 会慢
🚀 Web 项目不依赖 Conda 的强项 你不需要 NumPy、Pandas、SciPy 这类科学计算库

如何创建虚拟环境(Django项目)

  1. 查看自己的python用的是哪个版本:

    (base) xxxx@xxxxdeMacBook-Pro LinNote % which python3       
    /usr/bin/python3
    (base) xxxx@xxxxdeMacBook-Pro LinNote % which python 
    python: aliased to /opt/miniconda3/bin/python3
    
  2. 创建项目根目录

    mkdir LinNote
    cd LinNote
    
  3. 创建虚拟环境

    python -m venv .venv
    
    部分 含义
    python 表示用 Python 3 的解释器执行命令
    -m venv 表示运行 Python 内置模块 venv,这是用来创建虚拟环境的模块
    .venv(最后这个) 是你要创建的虚拟环境的目录名,你可以自己起名,比如 envvenvmyenv
  4. 激活虚拟环境

    source .venv/bin/activate   # Linux/macOS
    .venv\Scripts\activate      # Windows
    
  5. 安装依赖

    pip install django
    
  6. 使用Django创建项目: 在当前目录创建项目

    django-admin startproject LinNote .
    
  7. 导出依赖

    pip freeze > requirements.txt
    

    requirements.txt的内容如下:

    asgiref==3.8.1
    Django==5.2.1
    sqlparse==0.5.3
    
  8. 最后的目录结构:

    LinNote/
    ├── .venv/
    ├── LinNote/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── manage.py
    ├── requirements.txt
    

    但是,如果我们运行的是django-admin startproject LinNote,那么最终的目录会是这样的:

    LinNote/                      ← 顶级文件夹(项目外层)
    ├── .venv/                                        ← ❌ 虚拟环境和manage.py不是在同一层
    ├── LinNote/                 ← 实际项目目录
    │   ├── blog/
    │   ├── LinNote/
    │   ├── manage.py
    │
    └── requirements.txt         ← 放在顶级目录
    

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com

×

喜欢就点赞,疼爱就打赏