2025年7月8日更新:改区域方法不再推荐,经过测试日常使用会遇到软件文档编码错乱的问题。
win11开始搜索区域,“区域设置”→“管理”→“更改系统区域设置”里勾上「使用 Unicode UTF-8 提供全球语言支持(Beta)」。所有控制台/管道默认都用 UTF-8。
优点:解决兼容maya2023 python3编码兼容的问题,用vscode插件商店自带的mayaCode即可直接联通maya和vscode
缺点:windows的beta版本暗示可能未来会遇到奇怪的bug。
--------------------以下是原文使用第三方脚本转换的方法----------------
我最初尝试了网上最简单的方式的用vscode自带插件的 Mayacode/mayaport/sendtomaya等一系列一键开启端口发送代码的
插件,但都因由对maya2023 Python 3 的兼容性不足而放弃。
就为什么不能用vs的插件本人百思不得其解?我后来翻到github上去看了原插件下的留言区,最多留言的评论区给出了正确使用插件一种方式,竟与我后来摸索出的去掉echoOutput只输入 commandPort -name "localhost:7001" -sourceType "mel"来链接方式是一样,其实到这里,老外就可以使用vs傻瓜插件连上的,但是问题就咱们国内社区很多人用的maya是中文的。。。并且令人蛋疼的是而且只要脚本存在一个中文,哪怕是注释不是全英的,都会引入一个新的bug。即——编码错误。编码真的也是万能巨坑了..........这个有时间我真的要好好拜读一下文献搞搞清楚,眼下就是我各种百度后,虽在评论区看到了可能语言有关的提示,但再尝试了知乎大神说的在脚本开头写编码各种方式统统无果,始终无法解决vscode到maya端内部编码转换的问题,只得放弃
# Error: line 1: UnicodeDecodeError: file <maya console> line 1: 'gbk' codec can't decode byte 0x80 in position 173: illegal multibyte sequence
最终采用自定义 Python 脚本的方案。这个方法比较麻烦且折腾,建议不想折腾的,建议放弃vscode,投入pycharm的怀抱。笔记随便写了一下,先随便写写有空来完善。。。。。如果有大神能解决一下咱们中文区特有debuff问题,那将感激不尽。。。
1. 核心思路:通过 commandPort
发送“启动器”代码
即maya接收与vscode发送,通过一个脚本来解决兼容性的问题,在用一个task任务去跑传送。发送Python 字符串给 Maya 的 commandPort
。这个字符串充当一个“启动器”,负责在 Maya 内部:
- 正确配置 Python 环境(添加脚本路径到
sys.path
)。 - 重新加载目标脚本作为模块。
- 调用目标模块中预定义好的入口点函数。
2. 详细解决步骤
步骤 1:在 Maya 中开启端口commandPort
import maya.cmds as cmds
try:
cmds.commandPort(name=":7002", close=True) # 尝试关闭旧端口,可忽略错误
except RuntimeError:
pass
# 关键:不带 echoOutput=True,因为 Maya 2023 会报错
cmds.commandPort(name=":7002", sourceType="python")
print("Python commandPort ':7002' opened.") # 在 Maya 脚本编辑器确认端口开启
maya低版本用的cmds.commandPort(name="localhost:7002", sourceType="python", echoOutput=True) 完美兼容python2,但是echoOutput到了maya2023就出问题了。写进去吧,脚本编辑器会反复报类型错误,你不加进去吧,maya脚本编辑器根本读不到vscode发送的代码,不管是正常还是异常一律啥都不报,非常蛋疼!!!!!我几乎一晚上都栽在这了,研究很久后才发现是echoOutput有问题。。。吐血。。因此只能通过第三方脚本来定义脚本编辑器怎么输入输出。
2、测试自己的脚本经过我多个脚本测试并不是每个脚本都能跑通。。。
3、创建send_to_maya.py放在工程目录下,
脚本兼容性的问题让ai去弄吧
import socket
import sys
import os
import importlib # 确保这里导入了 importlib,在本地 send_to_maya.py 中使用
HOST = 'localhost'
PORT = 7002
def send_to_maya_and_execute(target_script_path):
module_name = os.path.basename(target_script_path).replace(".py", "")
script_dir = os.path.dirname(target_script_path)
script_dir_maya_format = os.path.normpath(script_dir).replace('\\', '/')
maya_command_string = f"""
import sys
import os
import importlib # 导入 importlib,因为这是在 Maya 内部执行的代码
# *** 核心修改:确保 reload 在使用前被导入 ***
from importlib import reload
# 确保脚本目录在 Maya 的 Python 搜索路径中
script_dir_in_maya_sys_path = r"{script_dir_maya_format}"
if script_dir_in_maya_sys_path not in sys.path:
sys.path.append(script_dir_in_maya_sys_path)
print(f"send_to_maya.py (Maya): Added {{script_dir_in_maya_sys_path}} to sys.path.")
# === 健壮的模块导入/重新加载逻辑 ===
# 定义一个变量来存储导入的模块对象
_module_obj = None
try:
if '{module_name}' in sys.modules:
_module_obj = reload(sys.modules['{module_name}'])
print(f"send_to_maya.py (Maya): Reloaded module '{module_name}'.")
else:
# 使用 __import__ 来动态导入模块,并确保赋值给 _module_obj
_module_obj = __import__('{module_name}')
print(f"send_to_maya.py (Maya): Imported module '{module_name}'.")
except Exception as e:
print(f"send_to_maya.py (Maya): Error importing/reloading module '{module_name}': {{e}}")
# 如果导入/重新加载失败,直接退出 Maya 端的执行,避免后续的 NameError
sys.exit()
# 将导入的模块对象赋值给与模块名相同的变量名,以便后续通过 . 访问
globals()['{module_name}'] = _module_obj
# === 调用模块中的入口点函数 ===
try:
# 直接使用模块名变量来调用函数
{module_name}.run_cam_vis_ui()
print(f"send_to_maya.py (Maya): Called {module_name}.run_cam_vis_ui().")
except Exception as e:
print(f"send_to_maya.py (Maya): Error calling {module_name}.run_cam_vis_ui(): {{e}}")
""" # 结尾不要有多余的空白行,不然 Maya 可能解析错误
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(maya_command_string.encode('utf-8'))
print(f"Sent to Maya:\n{maya_command_string}")
s.settimeout(1.0)
try:
response = s.recv(4096).decode('utf-8', errors='ignore')
if response:
print(f"\nMaya Response:\n{response.strip()}")
else:
print("\nMaya Response: (None - due to echoOutput limitation or no direct response)")
except socket.timeout:
print("\nMaya Response: (No response received within timeout - expected if echoOutput is off)")
except Exception as e:
print(f"\nMaya Response: (Error receiving response: {e})")
except ConnectionRefusedError:
print(f"Error: Could not connect to Maya command port at {HOST}:{PORT}.")
print("Please ensure Maya is running and commandPort is open (Python type).")
except Exception as e:
print(f"An unexpected error occurred in send_to_maya.py: {e}")
if __name__ == "__main__":
if len(sys.argv) > 1:
target_script_path = sys.argv[1]
print(f"Attempting to send script: {target_script_path}")
send_to_maya_and_execute(target_script_path)
else:
print("Error: No target script path provided to send_to_maya.py.")
print("Usage: mayapy send_to_maya.py <path_to_your_maya_script.py>")
4、配置 VS Code 任务 (tasks.json
)确保 VS Code 能够正确调用 mayapy.exe
来运行你的发送脚本,并将正确的参数传递过去。
shift+P搜索task-任务-配置任务,随便创建个模板,将tasks.json保存在项目目录下
,使其能够通过 mayapy.exe
执行 send_to_maya.py
,并将当前在 VS Code 中打开的 Python 文件的完整路径作为参数传递给它。
{
"version": "2.0.0",
"tasks": [
{
"label": "Send Python Code to Maya (Custom)",
"type": "shell",
"command": "C:/Program Files/Autodesk/Maya2023/bin/mayapy.exe", // 使用 Maya 的 Python 解释器
"args": [
"${workspaceFolder}/send_to_maya.py",
"${file}" // 将当前打开的文件路径作为参数
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}
5、在vscode的自己的maya脚本里Ctrl+shift+P,搜索run task运行任务,选择,即可在maya里看到内容