教程1:用vscode->ptvsd-创建和调试一个UI(python)-转载官方翻译(有修正)

vscode用python开发maya联动调试设置
3dsMax Python开发环境搭建
3文联动之debugpy调试max'python.
3文联动之socket插槽注入max'python

本教程是max主动接收创建代码的方式(预先运行界面,通过按钮主动读取py脚本,执行断点),虽然绕过了pymxs不能在外部编辑器里运行,但是这种方式并不优雅(理想)~~

从外部进程访问3ds Max API存在权限问题

Max 2018 (Python 2.7) + VSCode (maxPlus)→ 不支持远程 attach。

调试器有Eclipse公司 的pydevd,微软vs的ptvsd(py2.7,3.0+)->debugpy (py30+),max自身的maxPlus(非远程调试)

你要么用 Eclipse的PyCharm + pydevd,要么在用微软的 VSCode + (ptvsd)里退而求其次(用日志 / socket 打印调试)

要么升级 Max 到 2021+(Python 3.6+)支 持 debugpy。

在这个教程中,我们将使用visualsudio code和Python模块ptrsd(python TodksforWisualsudioDebugger)创建并调试一个名为"pyamid" 的小型3ds Maxprside2工具。该工具显示一个带有按钮的Q对话框,按下技

钮会在当前场景中添加一个黑色金字塔。

完成的教程代码可以在本主题末尾找到,供参考。
先决条件

本教程系列需要以下条件:

·安装了3ds Max2021或更高版本

·启动了3ds Max2021或更高版本,并使用Python3解释器(默认设置)

·已安装VS Code和Python扩展

·安装了PS6的3ds Max Python(参见使用pip与Python3)
创建项目

这个项目将被命名为pyramid。PEP-8(Python风格指南)建议模块使用小写的名称。

所以在我们的文件系统中的某个地方,创建一个嵌套的目录集,两者都命名为'pyramid':

python 复制代码
mkdir -p pyramid/pyramid

我们最终会使用这个目录结构,为我们的项目添加适当的 pip 包装信息。在本教程中,我们只需在其中创建程序
启动 VS Code

·开始与代码

·使用File>OpenFolder选择我们的顶级pyramid文件夹
创建源文件

我们的项目很小,但我们将将其分为两个文件以模拟一个更大的项目。

pyramid 子目录中创建一个名为ui.py 的新文件,然后添加以下代码:

python 复制代码
"""
    Provide a PySide2 dialog for the pyramid tool.
"""
from PySide2.QtWidgets import QWidget, QDialog, QLabel, QVBoxLayout, QPushButton
from pymxs import runtime as rt
from .graphics import make_pyramid_mesh

class PyMaxDialog(QDialog):
    """
    Custom dialog attached to the 3ds Max main window
    Message label and action push button to create a pyramid in the 3ds 
    Max scene graph
    """
    def __init__(self, parent=QWidget.find(rt.windows.getMAXHWND())):
        super(PyMaxDialog, self).__init__(parent)
        self.setWindowTitle('Pyside2 Qt Window')
        self.init_ui()

    def init_ui(self):
        """ Prepare Qt UI layout for custom dialog """
        main_layout = QVBoxLayout()
        label = QLabel("Click button to create a pyramid in the scene")
        main_layout.addWidget(label)

        btn = QPushButton("Pyramid")
        btn.clicked.connect(make_pyramid_mesh)
        main_layout.addWidget(btn)

        self.setLayout(main_layout)
        self.resize(250, 100)

建立一个其他的文件名graphics.py在同一个目录里, 并且添加代码:

python 复制代码
"""
    Provide the graphic functionality for the pryamid tool.
"""
from pymxs import runtime as rt

def make_pyramid_mesh(side=20.0):
    '''Construct a pyramid from vertices and faces.'''
    halfside = side / 2.0
    pyr = rt.mesh(
        vertices=[
            rt.point3(0.0, 0.0, side),
            rt.point3(-halfside, -halfside, 0.0),
            rt.point3(-halfside, halfside, 0.0),
            rt.point3(halfside, 0.0, 0.0)
            ],
        faces=[
            rt.point3(1, 2, 3),
            rt.point3(1, 3, 4),
            rt.point3(1, 4, 2),
            rt.point3(2, 3, 4),
        ])
    rt.redrawViews()
    return pyr

在这个位置你将有以下的目录结构:

python 复制代码
pyramid/
    pyramid/
        ui.py
        graphics.py

等等,我看到我的导入语句有问题。

Visualstudio code 使用一个代码检查工具来验证导入,默认情况下,它不知道在哪里查找 3ds MaxPython模块。自动补全系统也可能存在理解源代码方面的问题。为了解决这个问题,请将Visualstudio Code指向3ds Max的Python解释器:

通过文件>首选项设置打开设置

·在设置页面中,打开扩展>Python>自动完成:额外路径>在settings.json中编辑。这将打开settings.json文件。

添加:

python 复制代码
  ,
    "python.pythonPath": "C:\\Program Files\\Autodesk\\3ds Max 2021\\Python37\\python.exe",
    "python.autoComplete.extraPaths": [         
        "C:\\Program Files\\Autodesk\\3ds Max 2021\\Python37"     
    ] 

有关此问题的更多信息,请参见此处和此处。

在3ds Max中运行项目的第一版

切换到3ds Max,打开监听器窗口并选择Python选项卡。此时,我们应该看到监听器中显示的版本字符串表明正在使用Python 3.默认情况下,3dsMaxPython 解释器不知道示例的位置,但我们希望能够通过导入使其可用。因此,我们可以在Python监听器中键入此内容(用您自己的路径替换append 函数): 直接在监听窗口这里输出py执行,似乎没有反应的。

python 复制代码
import sys
sys.path.append(r'd:\sources\hacking\python\pyramid')

注意:逐行输入,使用CtrltEnter执行它们。

然后输入:

python 复制代码
import pyramid.ui
dialog = pyramid.ui.PyMaxDialog()
dialog.show()

这将显示对话框

如果你按下Pyramid按钮,你会得到一个异常:

现在我们需要调试这个问题。

从VS Code调试3ds Max的Python代码

在我们能够使用调试器来调试3ds Max中的Python代码之前,我们需要安装ptvsd(VisualStudio调试服务器的Python工具):

在你的3ds Max Python 3目录中,在命令行x:\Program Files\Autodesk\3ds Max 2024\Python>中,输入:

复制代码
python -m pip install --user ptvsd

安装完成的样子

在3ds Max端启用调试器

ptvsd调试服务器需要在3ds Max Python解释器中运行。在3ds Max监听窗口中,输入:

python 复制代码
import ptvsd
ptvsd.enable_attach()

这应该显示:

python 复制代码
('0.0.0.0', 5678)

这里但是!直接输出python是没有反应的。

那只有这样了,做成一个py文件保存,ctrl+e运行。

代码如下

复制代码
import sys
sys.path.append(r'd:\sources\hacking\python\pyramid')
import pyramid.ui
dialog = pyramid.ui.PyMaxDialog()
dialog.show()

(在我们的3ds Max会话中,无需重复上一步操作)。

第一次与Vs Code连接

3dsMax现在已准备好接受来自VS Code的连接,但我们仍需告诉vs Code如何与3dsMax进行连接。首次尝试与3dsMax连接时,需要在VS code中添加远程调试配置。

在VS Code中,选择运行>添加配置。

从下拉列表中选择远程附加。

然后按回车键选择localhost(默认)然后按回车键选择5678(默认值)

这将添加一个看起来像这样的配置代码:

python 复制代码
   {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ]
        }

我们不需要修改这个,除了我们需要指向

直接在我们的源处设置remoteRoot

python 复制代码
   "remoteRoot": "${workspaceFolder}",

此配置只需设置一次。

如果我们也想调试第三方模块(例如在pyside2代码中设置断点),虽然这在本次示例中不会实现,但这是一个非常常见的调试任务,我们还需要通过在 JSON 文件中添加以下内容来启用它.

python 复制代码
"justMyCode": false

最后,你的Launch.json 配置文件是这样的:(官方代码里没有版号和configuaratiions是不能正常运作的,端口号和localhost及得在connect字段里,排在前面的字段后面的逗号记得加)

python 复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "justMyCode": false,
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "${workspaceFolder}"
                }
            ]
        }
    ]
}

连接到vs Code

首先通过选择View>Open View... 并选择"Run and Debug"来打开运行和调试视图。我们需要在VS Code中选择调试配置:

确保选择了我们的 Python:Remote Attach 配置。在这种情况下,我们可以通过在 Vs Code 菜单中选择"调试""开始调试"来将调试器连接到 3ds Max Python.如果我们回到3ds Max,我们会看到UI不再冻结。然而,我们的程序仍然没有运行。运行程序

要运行我们的脚本,我们需要在3ds Max监听器窗口中输入:

python 复制代码
dialog.show()

这将运行我们想要但不起作用的对话框。

添加断点

通过我们程序之前的运行,我们知道graphics.py的第11行存在一个问题。因此,在VScode中,我们可以通过点击该行左侧的边距来添加断点:

触发断点

此时,当你点击对话框中的**Pyramid**按钮时,你的断点将被到达,并且你将在VS Code中看到它被高亮显示。

你可以检查局部变量,你会发现 side 变量是 False,这不是我们想要的。

修复代码

发生的问题是side为False。我们将make_pyramid mesh()连接到对话框按钮的代码如下:

python 复制代码
  btn.clicked.connect(make_pyramid_mesh)

这是有误的,因为btn.cicked 传递给我们的是一个布尔值,它告诉我们按钮是否处于选中状态。我们的代码接收了这个布尔值,而不是我们期望的默认值 20.0.因此我们可以修改这段代码,传递一个将side设置为20.0的lambda函数。

python 复制代码
  btn.clicked.connect(lambda: make_pyramid_mesh(20.0))

然后我们保存

使新代码运行

为了将控制权交还给max,我们按下F5(运行->继续)。我们看到3ds Max再次变得响应。关闭对话框

在监听器窗口的Python命令提示符中输入

python 复制代码
import importlib

然后

python 复制代码
importlib.reload(pyramid.ui)

这显示类似的内容:

python 复制代码
<module 'pyramid.ui' from 'd:\\sources\\hacking\\python\\pyramid\\pyramid\\ui.py'>

我们现在必须通过以下操作重新创建一个全新的对话版本:

python 复制代码
dialog = pyramid.ui.PyMaxDialog()

然后:

python 复制代码
dialog.show()

临时的aaa.py内容如下

python 复制代码
import sys
sys.path.append(r'd:\sources\hacking\python\pyramid')
import pyramid.ui
import importlib
importlib.reload(pyramid.ui)
dialog = pyramid.ui.PyMaxDialog()
dialog.show()

我们的断点已到达,但此时 side=20 和 halfside=10 。如果我们按 F5,代码现在将成功完成,并在视图中显示我们的黑色金字塔。

完整代码:

ui.py:

python 复制代码
"""
    Provide a PySide2 dialog for the pyramid tool.
"""
from PySide2.QtWidgets import QWidget, QDialog, QLabel, QVBoxLayout, QPushButton
from pymxs import runtime as rt
from .graphics import make_pyramid_mesh

class PyMaxDialog(QDialog):
    """
    Custom dialog attached to the 3ds Max main window
    Message label and action push button to create a pyramid in the 3ds 
    Max scene graph
    """
    def __init__(self, parent=QWidget.find(rt.windows.getMAXHWND())):
        super(PyMaxDialog, self).__init__(parent)
        self.setWindowTitle('Pyside2 Qt Window')
        self.init_ui()

    def init_ui(self):
        """ Prepare Qt UI layout for custom dialog """
        main_layout = QVBoxLayout()
        label = QLabel("Click button to create a pyramid in the scene")
        main_layout.addWidget(label)

        btn = QPushButton("Pyramid")
        btn.clicked.connect(lambda: make_pyramid_mesh(20.0))
        main_layout.addWidget(btn)

        self.setLayout(main_layout)
        self.resize(250, 100)

graphics.py:

python 复制代码
"""
    Provide the graphic functionality for the pryamid tool.
"""
from pymxs import runtime as rt

def make_pyramid_mesh(side=20.0):
    '''Construct a pyramid from vertices and faces.'''
    halfside = side / 2.0
    pyr = rt.mesh(
        vertices=[
            rt.point3(0.0, 0.0, side),
            rt.point3(-halfside, -halfside, 0.0),
            rt.point3(-halfside, halfside, 0.0),
            rt.point3(halfside, 0.0, 0.0)
            ],
        faces=[
            rt.point3(1, 2, 3),
            rt.point3(1, 3, 4),
            rt.point3(1, 4, 2),
            rt.point3(2, 3, 4),
        ])
    rt.redrawViews()
    return pyr

父页: 教程

下一页:教程2-添加NumPy,一个外部组件

相关推荐
萧鼎18 分钟前
深入理解 Python Scapy 库:网络安全与协议分析的瑞士军刀
开发语言·python·web安全
木宇(记得热爱生活)3 小时前
一键搭建开发环境:制作bash shell脚本
开发语言·bash
Cisyam^3 小时前
Go环境搭建实战:告别Java环境配置的复杂
java·开发语言·golang
名难取aaa3 小时前
celery solo acks_late得不到预期
python·celery
IAR Systems4 小时前
在IAR Embedded Workbench for Arm中实现Infineon TRAVEO™ T2G安全调试
开发语言·arm开发·安全·嵌入式软件开发·iar
jayzhang_4 小时前
SPARK入门
大数据·开发语言
蹦极的考拉4 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
fured4 小时前
[调试][实现][原理]用Golang实现建议断点调试器
开发语言·后端·golang
大翻哥哥5 小时前
Python地理空间数据分析:从地图绘制到智能城市应用
开发语言·python·数据分析