Jak*_*umm 7 c++ python debugging visual-studio-code pybind11
我想在 VSCode 中以“混合模式”运行和调试我自己的 Python C++ 扩展。由于定义自己的 python 包装器可能非常乏味,因此我想用它pybind11来链接 C++ 和 python。我喜欢 vscode 的调试工具,所以我想在 vscode 中调试我的 python 脚本以及 C++ 函数。
幸运的是,通过首先启动 python 调试器,然后将 gdb 调试器附加到该进程,可以同时调试 python 和 C++ 文件,如nadiah 的博客文章中详细描述的(Windows 用户,请注意这个问题)。这对我来说效果很好。不幸的是,他们手动定义了 C++ - python 绑定。我想用pybind11它来代替。
我使用 . 创建了一个与 nadiah 的示例一致的简化示例pybind11。调试 python 文件可以工作,但 gdb 调试器不会在.cpp文件中停止。根据这个github问题,理论上应该是可能的,但没有关于如何实现这一点的详细信息。
在这里,我尝试尽可能地遵循 nadiah 的示例,但包括pybind11包装器。
创建虚拟环境(也适用于 anaconda,如下所述)
virtualenv --python=python3.8 myadd
cd myadd/
. bin/activate
Run Code Online (Sandbox Code Playgroud)
创建文件myadd.cpp
#include <pybind11/pybind11.h>
float method_myadd(float arg1, float arg2) {
float return_val = arg1 + arg2;
return return_val;
}
PYBIND11_MODULE(myadd, handle) {
handle.doc() = "This is documentation";
handle.def("myadd", &method_myadd);
}
Run Code Online (Sandbox Code Playgroud)
,myscript.py
import myadd
print("going to ADD SOME NUMBERS")
x = myadd.myadd(5,6)
print(x)
Run Code Online (Sandbox Code Playgroud)
和setup.py
from glob import glob
from distutils.core import setup, Extension
from pybind11.setup_helpers import Pybind11Extension
def main():
setup(name="myadd",
version="1.0.0",
description="Python interface for the myadd C library function",
author="Nadiah",
author_email="nadiah@nadiah.org",
ext_modules=[Pybind11Extension("myadd",["myadd.cpp"])],
)
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
克隆 pybind11 存储库
git clone git@github.com:pybind/pybind11.git
Run Code Online (Sandbox Code Playgroud)
并安装python包
pip install pybind11
Run Code Online (Sandbox Code Playgroud)
运行安装脚本
python3 setup.py install
Run Code Online (Sandbox Code Playgroud)
现在,我们已经可以运行python脚本了
python myscript.py
Run Code Online (Sandbox Code Playgroud)
打开vscode
code .
Run Code Online (Sandbox Code Playgroud)
Ctrl使用+ Shift+ p-> Select python interpreter->选择 python 解释器./bin/python,现在在下部栏中,您应该看到 virtualenv myadd。launch.json通过单击调试符号和“创建新的启动配置”来创建文件。这是我的launch.json(这可能是问题所在)
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python",
"type": "python",
"request": "launch",
"program": "myscript.py",
"console": "integratedTerminal"
},
{
"name": "(gdb) Attach",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/bin/python", /* My virtual env */
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"additionalSOLibSearchPath": "${workspaceFolder}/build/lib.linux-x86_64-3.8;${workspaceFolder}/lib;${workspaceFolder}/lib/python3.8/site-packages/myadd-1.0.0-py3.8-linux-x86_64.egg/"
}
]
}
Run Code Online (Sandbox Code Playgroud)
请注意,我"additionalSOLibSearchPath"根据github 问题添加了该选项,但它没有改变任何内容。
在 vscode 中,在myscript.py第 5 行和第 7 行以及myadd.cpp第 5 行中添加断点。现在,首先启动 python 调试器并让它停在第 5 行的断点处。然后转到终端并获取正在运行的正确进程 ID蟒蛇脚本。
ps aux | grep python
Run Code Online (Sandbox Code Playgroud)
就我而言,倒数第二个过程是正确的。例如
username **65715** 3.0 0.0 485496 29812 pts/3 Sl+ 10:37 0:00 /home/username/myadd/bin/python /home/username/.vscode/extensions/ms-python.python-2022.0.1814523869/pythonFiles/lib/python/debugpy --connect 127.0.0.1:38473 --configure-qt none --adapter-access-token ... myscript.py
Run Code Online (Sandbox Code Playgroud)
在此示例中,65715将是正确的进程 ID。现在,在 vscode 中启动 (gdb) Attach 调试器并在搜索栏中输入进程 ID。按 Enter 键,现在您需要y在控制台中输入以允许附加并输入您的 sudo 密码。如果您遵循 nadiah 的示例,现在可以按 python 调试栏上的“继续”,脚本将在 C++ 断点处停止。对于此 pybind11 示例,脚本不会在 C++ 断点处停止。
您的项目结构现在应该如下所示
myadd
| bin/
| build/
| dist/
| lib/
| myadd.cpp
| myadd.egg-info/
| myscript.py
| pybind11/
| setup.py
Run Code Online (Sandbox Code Playgroud)
正如github 帖子中所述,必须确保设置了调试标志。因此,我添加了一个setup.cfg文件
[build_ext]
debug=1
[aliases]
debug_install = build_ext --debug install
Run Code Online (Sandbox Code Playgroud)
然后跑了
python setup.py debug_install
Run Code Online (Sandbox Code Playgroud)
但这也没有帮助。
使用 conda 代替 virtualenv 非常简单。只需像往常一样创建您的环境,然后输入
which python
Run Code Online (Sandbox Code Playgroud)
获取 python 可执行文件的路径。将您的调试配置"program"中的替换为此路径。(gdb) Attachlaunch.json
我跑
我认为 C++ 代码不是使用调试信息构建的。将关键字参数添加extra_compile_args=["-g"]到Pybind11Extensionin中setup.py可能足以解决该问题。
不管怎样继续阅读我的解决方案提案,这对我有用。
我可以通过使用BeniBenj 的 Python C++ 调试器扩展、设置 C++ 标志-g并使用--no-cleanpip 标志来完成这项工作。为了完整起见,我将在此附上我的最小工作项目。
在文件中创建绑定add.cpp:
#include <pybind11/pybind11.h>
float cpp_add(float arg1, float arg2) {
float return_val = arg1 + arg2;
return return_val;
}
PYBIND11_MODULE(my_add, handle) {
handle.doc() = "This is documentation";
handle.def("cpp_add", &cpp_add);
}
Run Code Online (Sandbox Code Playgroud)
创建测试 python 脚本:
import my_add
if __name__ == "__main__":
x = 5
y = 6
print(f"Adding {x} and {y} together.")
z = my_add.cpp_add(x, y)
print(f"Result is {z}")
Run Code Online (Sandbox Code Playgroud)
创建setup.py文件:
import os
from distutils.core import setup
from pybind11.setup_helpers import Pybind11Extension
setup(name="myadd",
version="1.0.0",
ext_modules=[Pybind11Extension("my_add", ["add.cpp"], extra_compile_args=["-g"])],
)
Run Code Online (Sandbox Code Playgroud)
该文件的重要之处setup.py在于它使用调试信息构建 C++ 代码。我怀疑这就是你所缺少的。
该软件包可以通过以下方式安装:
pip install --no-clean ./
Run Code Online (Sandbox Code Playgroud)
这--no-clean很重要。它可以防止调试器尝试打开的源被删除。
现在是启动 Python 和 C++ 调试器的时候了。我正在使用BeniBenj 的 Python C++ 调试器扩展,正如创建者在 Github 问题中所推荐的那样。安装后,只需单击“创建 launch.json 文件”,选择“Python C++ 调试器”,然后从选项中进行选择,即可创建调试配置。(对我来说,既有效Default又Custom: GDB有效。)
在 python 和 C++ 代码中放置断点。(在 python 代码中,我建议将它们与绑定代码及其后的代码放在同一行。)选择脚本并运行“Python C++ 调试器”配置。代码应在输入时暂停,并且在刚刚打开的第二个终端上应出现此问题:
Superuser access is required to attach to a process. Attaching as superuser can potentially harm your computer. Do you want to continue? [y/N]
Run Code Online (Sandbox Code Playgroud)
回答y。开始调试。到达 Python 中的绑定代码后,您可能必须手动单击调用堆栈(在左侧的调试面板中)才能实际切换到 C++ 代码。
我无法在线找到如何在setup.py. 因此我查看了Pybind11Extension. 在那里我看到了这一行:
env_cppflags = os.environ.get("CPPFLAGS", "")
Run Code Online (Sandbox Code Playgroud)
这表明我可以使用环境变量设置标志,而且确实可以。setup.py我在函数之前添加了这一行setup():
os.environ["CPPFLAGS"] = "-g"
Run Code Online (Sandbox Code Playgroud)
然而,当我输入这个答案时,我还在 pybind11 源代码中看到了这个评论:
# flags are prepended, so that they can be further overridden, e.g. by
# ``extra_compile_args=["-g"]``.
Run Code Online (Sandbox Code Playgroud)
我测试了它,它也有效。但是,我在文档中找不到它。这是我在这里包含这些步骤的主要原因。
为我。当调试器在 C++ 代码中的断点处暂停时,它想要打开tmp/pip-req-build-o1w6len6/add.cpp. 如果--no-cleanpip安装中没有保留该选项,那么将找不到该文件。(我必须创建它并将源代码复制到其中。)
这是Custom:GDB配置,其中“miDebuggerPath”参数可以删除:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python C++ Debugger",
"type": "pythoncpp",
"request": "launch",
"pythonLaunchName": "Python: Current File",
"cppAttachName": "(gdb) Attach"
},
{
"name": "(gdb) Attach",
"type": "cppdbg",
"request": "attach",
"program": "/home/dudly01/anaconda3/envs/trash_env/bin/python",
"processId": "",
"MIMode": "gdb",
"miDebuggerPath": "/path/to/gdb or remove this attribute for the path to be found automatically",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
Run Code Online (Sandbox Code Playgroud)
这是默认配置:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python C++ Debugger",
"type": "pythoncpp",
"request": "launch",
"pythonConfig": "default",
"cppConfig": "default (gdb) Attach"
}
]
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4742 次 |
| 最近记录: |