教程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,一个外部组件

相关推荐
databook1 天前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar1 天前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780511 天前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_1 天前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机2 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i2 天前
drf初步梳理
python·django
每日AI新事件2 天前
python的异步函数
python