【问题标题】:Problem with debugging python modules in VSCode在 VSCode 中调试 python 模块的问题
【发布时间】:2019-08-07 10:49:50
【问题描述】:

我的python练习项目有以下目录结构:

.
├── data
├── ds-and-algo
├── exercises
|   ├── __init__.py
│   ├── armstrong_number.py
│   ├── extract_digits.py
├── output

extract_digits.py 看起来像这样:

def extract_digits(n):
    pass

armstrong_number.py 我有以下内容:

from .extract_digits import extract_digits

如果我运行,则从根项目目录

python exercises/armstrong_number.py

我收到ModuleNotFoundError: no module named exercises

使用-m 标志运行以下逗号可解决错误:

python -m exercises.armstrong_number

但是使用VSCode 来调试文件,我有以下调试配置launch.json

{
"version": "0.2.0",
    "configurations": [
        {
            "name": "Python Module",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "pythonPath": "${config:python.pythonPath}",
            "module": "exercises.${fileBasenameNoExtension}",
            "cwd": "${workspaceRoot}",
            "env": {"PYTHONPATH":"${workspaceRoot}"}
        }
    ]
}

但是这有一些问题:

1) 对于不同的文件夹,例如ds-and-algo,我得手动编辑launch.json文件调试配置中的模块入口为

"module" : "ds-and-algo.${fileBaseNameNoExtension}"

如果我有嵌套文件夹配置,例如:

exercises
├── tough
|   | __init__.py
|   ├──ex1.py
|   ├──ex2.py
├── easy

我再次必须手动将launch.json 文件中的调试配置编辑为:(考虑子文件夹tough 的情况)

"module": "exercises.tough.${fileBaseNameNoExtension}"

我需要实现一个一般情况,根据被调试的文件,launch.json 文件中的"module" 条目应该是:

"module": "folder1.folder2.folder3.....foldern.script"

就像fileBaseNameNoExtensionVSCodesome other predefined variables

其中一个变量是relativeFile,即当前打开的文件相对于workspaceFolder的路径 因此对于文件ex1.py,变量relativeFile 将是exercises/tough/ex1.py

我需要操作此字符串并将其转换为exercises.tough.ex1,如果我可以在launch.json 文件的"module" 条目中编写和执行bash 命令,这将是微不足道的。但我无法做到这一点。但是,链接predefined variables in VSCode 有一个关于命令变量的部分,其中指出:

如果上面的预定义变量不够用,您可以通过 ${command:commandID} 语法使用任何 VS Code 命令作为变量。

此链接包含许多其他可能有用的信息。我不是 python 专家,绝对不知道任何 javascript,如果这是解决这个问题所需要的。

【问题讨论】:

    标签: python visual-studio-code


    【解决方案1】:

    我无法重现您的错误:ModuleNotFoundError: no module named exercises

    使用以下文件

    exercises/extract_digits.py

    def extract_digits(n):
      return 10
    

    exercises/armstrong_number.py

    from extract_digits import extract_digits
    
    def armstrong_number(n):
      return extract_digits(n)
    
    if __name__ == "__main__": 
      print armstrong_number(3)
    

    如果您使用 Python3,请将 print 语句更改为:print(armstrong_number(3)) 并更改使用的 Python 解释器。

    如果你的当前目录是项目根目录并且你运行

    python exercises/armstrong_number.py
    

    您在控制台中获得数字 10


    在 Visual Studio Code 中,您使用了错误的启动配置。

    你只是在运行 python 程序,所以你应该使用Python: Current File 配置。 launch.json

    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Python: Current File",
          "type": "python",
          "request": "launch",
          "program": "${file}",
          "console": "integratedTerminal",
        }
      ]
    }
    
    1. 在任何目录中打开您要运行/调试的示例 py 文件。
    2. 或将其设为当前文件
    3. 选择调试侧栏
    4. 选择Python: Current File配置
    5. 点击“绿色”三角形。

    现在构建并运行了一个复杂的命令。它会将 CWD 设置为当前文件的目录,并在当前文件上启动调试器。


    如果您真的需要模块启动,您可以在 VSC 中使用 Multi-Root Workspace 并为每个根目录单独配置 launch.json


    如果您想使用${command:commandID} 语法,您可以构造一个使用activeTextEditor 的简单扩展名,并根据文件名构造一个字符串
    编辑

    另一种选择是使用多启动配置。

    我已删除默认值有效或未使用的属性。

    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Exercise",
          "type": "python",
          "request": "launch",
          "console": "integratedTerminal",
          "module": "exercises.${fileBasenameNoExtension}",
        },
        {
          "name": "Exercise.Easy",
          "type": "python",
          "request": "launch",
          "console": "integratedTerminal",
          "module": "exercises.easy.${fileBasenameNoExtension}",
        },
        {
          "name": "DS",
          "type": "python",
          "request": "launch",
          "console": "integratedTerminal",
          "module": "ds.${fileBasenameNoExtension}",
        }
      ]
    }
    


    您可以使用扩展名Command Variable 来获取这个带有点分隔符的相对目录。
    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Python: Module CmdVar",
          "type": "python",
          "request": "launch",
          "console": "integratedTerminal",
          "module": "${command:extension.commandvariable.file.relativeDirDots}.${fileBasenameNoExtension}",
        }
      ]
    }
    

    【讨论】:

    • 我的 armstrong_number.py 在导入模块之前有一个点 (.),如下所示:python from .extract_digits import extract_digits ,所以,python exercises/armstrong_number.py,给出以下错误:``` ModuleNotFoundError: No module named 'main.extract_digits'; 'main' 不是包 I don't want them to act like indiv scripts but a module part of a single project workspace. I do use the Current file config, but that's for one-off scripts. Not inside a project.activeTextEditor``` 和 ${command:commandID} 似乎是我真正需要的。但我不确定如何。
    • @AbhishekBhatia 另一个选项是:多个启动配置。查看我的编辑
    • 这真的有效!谢谢!我认为这是一个非常新的扩展,因为我必须将 vscode 从 1.36 更新到 1.37,才能安装它。
    【解决方案2】:

    我不确定是否要运行 bash 脚本,但如果可以在文件中运行 JavaScript,"ds-and-algo.(${fileBaseNameNoExtension}).split('/').join('.')" 应该可以解决问题。

    实际上,您需要-m 标志的原因是您的文件夹中没有__init__.py 文件。这些文件可能是空的,但 python 使用它们来识别模块结构,从而允许嵌套和相对导入。我希望添加这些文件可以让你只运行python exercises/armstrong_number.pypython ds-and-algo/tough/ex1.py

    【讨论】:

    • 我已经在文件夹中有__init__.py 文件。对不起,我忘了在树结构中提到这一点。我现在已经进行了编辑。我在launch.json 文件的模块条目中尝试了splitjoin 命令。我将文件编辑为具有 ``` "module": "${relativePath}.split('/').join('.')" ``` 但我认为它肯定会执行 bash 来评估我得到的表达式以下错误:```bash:意外标记附近的语法错误`('```
    【解决方案3】:

    没有办法在您的launch.json 中指定您希望它计算您要调试的模块是什么。这是因为在技术上不可能 100% 正确,因为命名空间包允许任何目录代表一个包。您最好的选择是为每个要在launch.json 中运行的示例创建单独的调试配置(您可以拥有任意数量的)。如果手工操作太繁琐,您可以编写一个 Python 脚本来为您生成 launch.json

    【讨论】:

    • 在开始调试之前,有没有办法可以在 VSCode 中自动将 python 脚本作为任务运行?基本上我希望launch.json 文件中的module 条目在每个文件中都不同。我想我需要阅读命名空间包才能真正了解我哪里出错了。
    • @AbhishekBhatia 不是我所知道的。你可以编写一个 Python 脚本并为它设置一个任务,这样你就可以在 VS Code 中轻松地运行它。并且根据您想要投入多少精力,您可以使用文件观察程序创建一个守护进程,以自动检测何时发生更改,然后自动更新launch.json。但这对于一次性问题来说可能工作量太大了。 :)
    猜你喜欢
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    相关资源
    最近更新 更多