Hexo

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

VSCode——Debug使用笔记


整体说明

  • VSCode Debug 大型项目是有一定难度和门槛的

Debug 的前置准备

安装必要插件

  • 打开 VSCode,左侧栏扩展(快捷键Ctrl+Shift+X),搜索并安装:
    • Python(微软官方,核心插件)
    • Python Debugger(新版调试核心,微软官方)
    • 可选:Pylance(增强代码提示,大型项目必备)

确认 Python 解释器

  • 大型项目通常用虚拟环境,Debug 是从 terminal 中启动的,需要在 terminal 先配置好环境
  • 快捷键 Ctrl+Shift+P,输入 Python: Select Interpreter

初始化调试配置文件(launch.json)

  • VSCode 调试依赖 launch.json 配置,大型项目需自定义配置以适配项目结构,步骤如下:

  • 1)打开项目根目录(关键:必须打开根目录,而非单个文件)

  • 2)打开调试面板:左侧栏 运行和调试 (快捷键Ctrl+Shift+D), 点击 创建 launch.json 文件

  • 3)选择调试环境:弹出的下拉框中选 Python,再选 Python File(基础模板,后续修改)

    • 默认生成的 launch.json 在 .vscode 文件夹下
  • 4)自定义 launch.json(这一步是核心!适配大型项目),修改为适合大型项目的配置,示例如下(注释说明关键参数):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    {
    "version": "0.2.0",
    "configurations": [
    {
    "name": "Python: 项目主入口", // 配置名称,可自定义
    "type": "debugpy", // 调试器核心,固定值
    "request": "launch", // 启动调试(而非附加进程)
    "program": "${workspaceFolder}/src/main.py", // 项目主入口文件(替换为你的实际路径)
    "cwd": "${workspaceFolder}", // 调试时的工作目录(固定为项目根)
    "args": ["--env", "dev", "--config", "configs/dev.yaml"], // 主程序运行参数(按需添加)
    "justMyCode": false, // 大型项目建议关闭,可调试第三方库/依赖代码
    "env": { // 自定义环境变量(如数据库地址、密钥等)
    "PYTHONPATH": "${workspaceFolder}", // 关键!解决大型项目模块导入问题
    "ENV": "development"
    },
    "envFile": "${workspaceFolder}/.env", // 加载.env文件(可选,管理环境变量)
    "stopOnEntry": false, // 启动后是否立即暂停(新手可设为true,熟悉后改false)
    "console": "integratedTerminal", // 调试输出到VSCode集成终端(方便看日志)
    "subProcess": true // 关键!调试子进程/子模块(大型项目多进程必备)
    },
    // 可选:添加调试单个模块/测试文件的配置
    {
    "name": "Python: 调试单个模块",
    "type": "debugpy",
    "request": "launch",
    "module": "src.utils.data_process", // 调试指定模块(替代program)
    "cwd": "${workspaceFolder}",
    "env": {"PYTHONPATH": "${workspaceFolder}"}
    }
    ]
    }
    • PYTHONPATH:将项目根目录加入 Python 路径,解决 模块找不到 问题(大型项目多目录结构必配);
    • subProcess:开启后可调试项目中通过 subprocess 启动的子进程;
    • args:传递给主程序的命令行参数(如配置文件路径、环境参数)

设置断点

  • 大型项目调试时应该避免 全局断点 ,需针对性设置:

基础断点

  • 点击代码行号左侧的空白处,出现红色圆点即断点生效(调试时运行到此处会暂停)

高级断点(非常好用)

  • 使用:右键断点红点 -> Edit Breakpoint,会出现多个选项可选,默认是 Expression
    • Expression :
      • 右键断点红点 -> Edit Breakpoint -> Expression -> 输入 Python 表达式(仅当表达式为 True 时暂停)
      • 示例:调试循环处理数据时,设条件 i == 100(仅第 100 次循环暂停,避免逐行调试)
      • 注意这个配置很好用,不需要修改代码,且可以是任意的语句
    • Log Messages :
      右键断点红点 -> Edit Breakpoint -> Log Messages -> 输入日志内容(如 "处理数据:{data_id}" )
      • 调试时不暂停,仅输出日志(适合排查循环/批量处理问题,不中断程序)

启动调试

  • 第一步:
    • 确认 launch.json 中选中目标配置
    • 比如调试面板顶部下拉框选 launch.json 中已经配置好的选项
  • 第二步:
    • 点击调试面板的 绿色三角按钮
    • 启动后程序运行到断点会暂停,顶部出现调试控制栏,核心按钮(从左到右):
  • 第三步:一些调试操作说明
    • 继续(F5):运行到下一个断点;
    • 单步跳过(F10):执行当前行,不进入函数内部(适合快速跳过无关代码);
    • 单步进入(F11):进入当前行调用的函数内部(调试子模块核心);
    • 单步退出(Shift+F11):从当前函数退出到调用处;
    • 重启(Ctrl+Shift+F5):重新启动调试;
    • 停止(Shift+F5):结束调试

附录:调试时查看数据

  • VSCode 提供多个面板 查看 查看变量/数据状态

变量面板

  • 自动显示当前作用域的所有变量(局部变量、全局变量、内置变量)
  • 可展开复杂对象(如字典、类实例)查看内部属性
  • 右键变量 -> 添加到监视 ,固定关注核心变量

监视面板

  • 手动输入 Python 表达式(如 len(data_list)、user.id == 123),实时显示结果;
  • 大型项目建议添加 核心状态变量 (如配置是否加载、数据库连接是否正常)
  • 监控面板的变量会固定长期展示(变化也会体现出来)

附录:调试大型项目的进阶技巧(避坑+效率提升)

技巧1:解决 模块导入失败 问题

  • 大型项目多目录结构(如 src/、tests/、configs/)易出现 ModuleNotFoundError,除了配置 PYTHONPATH,还可以尝试
    • 在项目根目录创建 __init__.py(空文件即可,标记为Python包);
    • 调试单个模块时,用 module 参数替代 program(如 launch.json 中 "module": "src.utils.data_process",而非直接指定文件路径)

技巧2:调试多线程/多进程项目

  • 多线程 :调试面板左侧 调用堆栈 -> 展开 线程 列表,切换不同线程查看状态;
  • 多进程 :
    • 若用 gevent 协程,需在 launch.json 中添加 "gevent": true
    • 普通进程使用 subProcess: true(子进程调试);
  • 进阶:使用 附加到进程 调试(调试面板 -> 添加配置 -> Python: 附加到进程 ,选择运行中的Python进程)

技巧3:调试测试用例(大型项目单元测试必备)

  • 安装 pytest(pip install pytest);

  • launch.json 添加配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    "name": "Python: test case",
    "type": "debugpy",
    "request": "launch",
    "module": "pytest",
    "args": ["tests/test_data_process.py::test_handle_data", "-v"],
    "cwd": "${workspaceFolder}",
    "env": {"PYTHONPATH": "${workspaceFolder}"}
    }
    • 启动后直接调试指定测试用例(精准定位单元测试失败问题)

技巧4:跳过无关代码(提升效率)

  • 大型项目调试时避免进入第三方库/无关模块:
    • 在 launch.json 中设置 "justMyCode": true(默认),调试时自动跳过 site-packages 中的第三方库代码
    • 若需调试自己写的子模块,确保模块路径在 PYTHONPATH 中,且代码在 ${workspaceFolder} 下

附录:其他问题总结

  • 若断点未触发:检查 launch.json 的 program 路径是否正确、断点是否在执行路径上、PYTHONPATH 是否配置

  • 若变量查看异常:确认当前作用域是否正确(如函数内部只能看局部变量)

  • 若调试卡顿:减少不必要的断点,优先用 日志断点 替代普通断点

  • 断点灰色(未生效):

    • 原因:文件不在项目根目录、解释器选错、launch.json 的 program 路径错误;
    • 解决:确认打开的是项目根目录,重新选择解释器,检查 program 路径是否为 ${workspaceFolder} 开头
  • ModuleNotFoundError:

    • 解决:配置 PYTHONPATH: "${workspaceFolder}",或在代码开头添加:
      1
      2
      3
      import sys
      from pathlib import Path
      sys.path.append(str(Path(__file__).parent.parent)) # 向上级目录添加到路径
  • 调试时终端无输出:

    • 解决:launch.json 中设置 "console": "integratedTerminal"(而非 internalConsole)

Python——uv工具的使用


整体说明

  • uv 是一个快速的 Python 包管理器和项目管理工具,由 Astral 公司开发,旨在替代 pip、venv 等工具,提供更快的安装速度和更简洁的使用体验
  • uv 通常比 pip 快 10-100 倍
  • uv 内置虚拟环境:无需单独管理虚拟环境
  • uv 支持项目管理:原生支持 pyproject.toml,详情见附录
  • uv 保持了与 pip 相似的命令行接口,对于熟悉 pip 的用户来说很容易上手,同时提供了更现代、更高效的功能

安装 uv

  • 安装 uv 工具:

    1
    2
    3
    4
    5
    # 使用 pip 安装
    pip install uv

    # 或者使用官方安装脚本(推荐)
    curl -LsSf https://astral.sh/uv/install.sh | sh
  • 安装完成后,可以通过 uv --version 验证是否安装成功

  • 若提示没有命令,可能是需要配置环境变量,将下面的命令添加到 ~/.bashrc 中即可:

    1
    source $HOME/.local/bin/env

uv 基本用法介绍

虚拟环境管理

  • uv 内置了虚拟环境管理功能,无需单独使用 venv 或 virtualenv:

    1
    2
    3
    4
    5
    6
    7
    # 创建并激活虚拟环境(会在当前目录创建 `.venv` 文件夹)
    uv venv
    source .venv/bin/activate # Linux/macOS 激活环境,切换到当前环境下
    deactivate # Linux/macOS 退出激活

    # 直接在虚拟环境中运行命令(无需手动激活)
    uv run python --version
  • 若使用 source .venv/bin/activate 激活环境

    • 像 conda 一样,会切换到指定的虚拟环境下,直接使用 which python 可访问到当前项目的 python 文件
    • 但此时 pip 不会像 conda 一样替换,还是需要使用 uv pip 来使用,直接使用 which pip 得到的还是通用的 pip

IDEA 环境配置

  • 在使用 uv venv 创建了虚拟环境以后,可以使用 IDEA 直接选择 ./.venv/bin/python 作为解释器

类似 pip 的包安装与管理

  • uv 可以像 pip 一样安装和管理 Python 包:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 安装包
    uv pip install requests

    # 安装特定版本的包
    uv pip install requests==2.31.0

    # 从requirements.txt安装
    uv pip install -r requirements.txt

    # 升级包
    uv pip install --upgrade requests

    # 卸载包
    uv pip uninstall requests

    # 查看已安装的包
    uv pip list

    # 导出依赖到requirements.txt
    uv pip freeze > requirements.txt

uv 运行 python 文件

  • 使用 uv run 可以在虚拟环境中直接运行命令,无需手动激活环境 :

    1
    2
    3
    4
    5
    6
    7
    8
    # 运行Python解释器
    uv run python

    # 运行脚本
    uv run script.py

    # 运行命令行工具(如pytest)
    uv run pytest tests/
  • 常用命令 uv run --locked:

    • --locked 是一个“断言锁文件是最新的”检查开关,强制要求 uv.lock 必须与 pyproject.toml 完全同步
      • 若不同步则直接报错退出,不会自动更新锁文件
        • **不加 --locked**:uv 在运行前通常会默默检查依赖,如果发现锁文件过时,它可能会自动更新 uv.lock(或提示你更新),然后继续执行
        • 加 --locked**:宁可报错,也绝不自动修改锁文件** ,是一种保护机制
    • 会检查以下内容
      • 执行 uv run --locked <命令> 时,uv 会对比项目配置文件(pyproject.toml 或 uv.toml)和锁文件(uv.lock)
        • 如果 pyproject.toml 里的依赖和 uv.lock 里记录的完全一致,则 命令正常执行
        • 如果 pyproject.toml 里的依赖有变动,但 uv.lock 还没更新 则 命令直接报错 ,不会运行后面的命令
  • 常用命令 uv run --frozen(与 --locked 比较):

    • --locked:检查 pyproject.toml 和 uv.lock 是否匹配(不匹配就报错)
    • --frozen:完全不读取 pyproject.toml,只认 uv.lock,即使 pyproject.toml 改了也忽略它

附录:uv 高级功能

缓存管理

  • uv 具有高效的缓存机制,可以手动管理缓存:
    1
    2
    3
    4
    5
    # 清理缓存
    uv cache clean

    # 查看缓存大小
    uv cache size

配置镜像源

  • uv 可以配置自己的 pip 源,配置国内镜像源加快下载速度,比如:

    1
    2
    # 设置 PyPI 镜像源
    export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple/
    • 注:也可以永久添加到环境变量中方便使用
  • 临时指定镜像源的方式为:

    1
    uv add <package> --index-url https://pypi.tuna.tsinghua.edu.cn/simple/
  • 安装时输出源信息:

    1
    uv add requests --verbose # 注意:谨慎打开 `--verbose` 这个参数,会输出特别长的日志

构建和发布包

  • uv 支持构建和发布 Python 包到 PyPI:
    1
    2
    3
    4
    5
    # 构建包
    uv build

    # 发布包到 PyPI
    uv publish

附录:uv 管理 python 项目

  • uv 支持现代 Python 项目管理,包括 pyproject.toml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 初始化新项目(创建 pyproject.toml)
    uv init my_project # 在当前目录下创建 my_project 文件夹并生成基本文件
    # 生成 README.md main.py pyproject.toml 等文件
    cd my_project

    # 添加依赖(会更新 pyproject.toml)
    uv add requests # 生产依赖,将 requests 添加到 pyproject.toml 的 dependencies 列表中同时安装 requests 及其依赖(注:requests 的依赖不会添加到 pyproject.toml 中)
    uv add --dev pytest # 开发依赖,仅开发阶段需要使用到的依赖(将 pytest 添加到 pyproject.toml 的 dev 列表中),pytest 就是最常见的开发依赖,prod 环境不需要

    # 安装项目依赖(根据 pyproject.toml)
    uv sync # 补充:uv sync 是一个“按锁同步”的命令,它会根据 uv.lock 文件来安装精确版本的依赖,它不会重新解析依赖或修改 uv.lock 文件,详情见附录

    # 运行项目中的脚本
    uv run my_script.py

补充:pyproject.toml 介绍

  • pyproject.toml 是现代 Python 项目的核心配置文件(TOML 格式)
    • 由 PEP 517/518/621 标准化
    • 可 替代传统的 setup.py/setup.cfg/requirements.txt
    • 实现统一管理项目构建、依赖、工具与元数据
pyproject.toml 的核心作用
  • 构建系统声明 :指定项目用什么工具构建(如 setuptools/hatch),解决“如何打包”的问题

    1
    2
    3
    [build-system]
    requires = ["setuptools>=61.0"]
    build-backend = "setuptools.build_meta"
  • 项目元数据 :定义项目名、版本、作者、描述、入口点等,用于发布与识别

  • 依赖管理 :声明运行/开发依赖(替代 requirements.txt),支持版本约束与分组

    1
    2
    3
    4
    [project]
    dependencies = ["torch>=2.0", "numpy"]
    [project.group.dev]
    dependencies = ["pytest", "black"]
  • 工具配置 :存放 uv/poetry/pytest 等工具的专属配置([tool.xxx])

  • 注:这 相当于 Node.js 的 package.json ,是项目的“配置中枢”

uv run xx.py 在执行什么

  • uv run xx.py 是 uv 工具的脚本执行命令 ,核心是在 uv 管理的隔离环境中运行 Python 脚本 ,背后做 3 件事:
    • 1)环境准备 :读取 pyproject.toml/uv.lock,确保依赖已安装(自动执行 uv sync 逻辑),并激活对应虚拟环境
    • 2)脚本执行 :调用 Python 解释器运行 xx.py,等价于 uv run python xx.py
    • 3)参数透传 :脚本后的所有参数直接传给 xx.py,和原生 python 一致
  • 相当于传统 Python 项目的什么命令
    uv 命令 传统 Python 等价操作(手动流程) 说明
    uv run xx.py 1. 激活虚拟环境(source venv/bin/activate)
    2. python xx.py
    uv 自动完成环境激活与依赖校验
    uv run python xx.py python xx.py(已激活虚拟环境) 完全等价
    uv run --frozen xx.py 跳过依赖检查,直接运行 对应部署场景的快速执行
  • TLDR: uv run xx.py ≈ 自动激活虚拟环境 + python xx.py ,省去手动管理虚拟环境的步骤

补充:uv lock 命令详解

  • uv lock 是 uv 的依赖解析引擎
    • 不会安装任何包,而是根据 pyproject.toml 中声明的约束条件,计算出所有依赖的精确版本和哈希值,并将这个确定性的依赖关系树写入 uv.lock 文件
  • uv lock 的详细执行步骤
    • 1)读取项目清单 (pyproject.toml) :解析项目直接依赖项(dependencies)、可选依赖项(optional-dependencies)、开发依赖项及项目元数据(如 requires-python)
    • 2)构建依赖图并解析冲突(核心) :
      • 获取所有直接依赖及其传递依赖(子依赖)
      • 根据 requires-python(Python 版本范围)过滤掉不兼容的包版本
      • 运行高级求解算法(类似于 pip-compile 但更快),解决版本冲突
        • 例如,如果 A 需要 B>1.0,而 C 需要 B<2.0,求解器会找到满足所有条件的版本(如 B=1.5)
    • 3)获取元数据(索引查询) :
      • 查询配置的 PyPI 镜像(或私有源),获取每个候选包的元数据(版本号、发布时间、依赖项、支持的系统平台等)
      • 如果需要,还会拉取 Git 仓库或本地路径包的元数据
    • 4)锁定平台特定标记(跨平台支持) :
      • uv 默认生成通用锁文件(Universal Locking)
      • 它会计算包在不同系统(Windows/Linux/macOS)上的 Wheels 兼容性(即 sys_platform 和 implementation_name 标记),确保锁文件在所有开发者机器和 CI/CD 环境上通用
      • 注意:这里是计算所有平台上的版本,也就是说解析后对所有平台都通用(可以理解为每个包的所有版本信息)
    • 5)确定精确版本 :为每个包选出符合约束条件的最新兼容版本(除非指定升级策略),这保证了项目所有成员安装的是同一个版本
    • 6)计算文件哈希(完整性校验) :计算每个锁定包的分发文件(Wheel 或源码包)的哈希值(SHA-256),并将其写入锁文件,以防止恶意篡改或源数据意外变更
    • 7)写入 uv.lock 文件 :将上一步生成的完整依赖树、精确版本、哈希值以及解析源(PyPI URL 或 Git 地址)以结构化格式写入 uv.lock
      • 后续将这个文件也上传到云端,可以保证每个用户安装的都是相同的版本
  • 常用选项与高级场景
    选项 作用
    uv lock --upgrade 升级所有依赖 :忽略 uv.lock 中现有的锁定版本,重新查找符合 pyproject.toml 约束的最新版本
    uv lock --upgrade-package <PACKAGE> 升级特定包 :仅针对指定的包进行升级,其余依赖保持锁定的版本不变
    uv lock --python-platform <PLATFORM> 锁定特定平台 :例如 --python-platform windows,用于为特定操作系统(如 Linux 服务器)生成锁文件,即使在 macOS 上开发
    uv lock --extra <EXTRA> 包含可选依赖 :将指定的可选依赖组纳入解析范围(常用于确保 dev 组和主依赖无冲突)
    uv lock --no-update 仅检查不更新 :如果 uv.lock 已存在且与 pyproject.toml 一致,则直接退出;若不一致则报错,而不生成新锁文件(常用于 CI 检查)

补充:uv sync 命令详解

  • uv lock 是制定施工蓝图 ,而 uv sync 是按蓝图施工
    • uv lock :只负责解析 ,根据 pyproject.toml 计算出所有依赖的精确版本,并写入 uv.lock 文件。它不会安装任何包
    • uv sync :只负责安装 ,读取现有的 uv.lock 文件,并将环境同步到该状态。它不会修改 uv.lock 文件
  • uv sync 用于将项目的虚拟环境与锁文件 (uv.lock) 的状态同步一致
    • 理解:可以把它看作一个更智能、更快速的 pip install -r requirements.txt + pip install -e .
  • uv sync 是一个“按锁同步”的命令,它会根据 uv.lock 文件来安装精确版本的依赖
    • 注意:它不会 重新解析依赖或修改 uv.lock 文件
  • uv sync 的详细执行步骤
    • 1)读取配置与检查环境 :从项目根目录的 pyproject.toml 中读取项目配置
      • 同时检查是否存在虚拟环境(默认是 .venv/),如果不存在则自动创建
    • 2)读取锁文件 (uv.lock) :读取 uv.lock 文件,获取需要安装的每一个包的精确版本号
      • 如果 uv.lock 不存在,uv sync 会自动执行 uv lock 来生成它
    • 3)安装依赖包 :根据 uv.lock 的内容,安装项目所需的所有依赖包。此步骤会:
      • 默认包含开发依赖 :会安装 [project.optional-dependencies] 中定义的所有可选依赖组,包括开发依赖(如 --dev 组)
      • 以可编辑模式安装项目 :将项目本身 以可编辑(-e)模式安装到虚拟环境中
        • 这意味着你对项目代码的修改会立即生效,无需重新安装
    • 4)执行“精确”同步(清理多余包) :这是 uv sync 的一个重要特性
      • 默认情况下,它会执行 “精确”同步 ,包括删除不必要的包
      • 这意味着,如果虚拟环境中存在任何不在 uv.lock 中的包 ,uv sync 会将其移除 ,以确保环境与锁文件完全一致
  • 常用选项与场景
    • uv sync --frozen:生产环境部署或需要绝对确定性时使用
      • 此命令不会检查或更新锁文件,直接根据现有的 uv.lock 安装
    • uv sync --no-dev:当不需要开发依赖时(如在生产环境)使用
      • 此命令会排除开发依赖的安装
    • uv sync --no-editable:当你不想以可编辑模式安装项目时使用
      • 项目会被正常安装,修改代码后需要重新执行 uv sync 才能生效
    • uv sync --inexact:当你希望保留环境中已有的、但不在锁文件中的额外包时使用
      • 此命令会跳过移除多余包的操作
    • uv sync --extra <EXTRA>:安装指定的可选依赖组时使用
      • 例如 uv sync --extra dev 或 uv sync --extra test
    • uv sync --all-packages:在大型项目(monorepo)中,需要同步工作区内所有子项目的依赖时使用
1…101102103…352
San Ye

San Ye

Stay Hungry. Stay Foolish.

704 posts
53 tags
© 2026 San Ye
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4