如何在exec嵌套compile的Python代码中传递命令行参数?
解决exec+compile传递命令行参数/输入的问题
问题背景
你目前通过以下代码在Blender内置编辑器中执行外部脚本,但不知道如何向被调用的代码传递参数或输入:
filename = 'C:\\temp\\script.py' exec(compile(open(filename).read(),filename, 'exec'))
解决方案
1. 修改sys.argv模拟命令行参数
如果被调用的脚本依赖sys.argv获取命令行参数,可以临时修改sys.argv,执行后恢复原值:
import sys filename = 'C:\\temp\\script.py' # 保存原始命令行参数 original_argv = sys.argv.copy() # 构造自定义参数,sys.argv[0]通常对应脚本路径,后续为参数 sys.argv = [filename, "--material-name", "CustomMat", "voronoi-scale", "200"] exec(compile(open(filename).read(), filename, 'exec')) # 恢复原始参数,避免影响后续逻辑 sys.argv = original_argv
此时被调用的script.py中可以通过sys.argv读取这些参数,例如:
import sys, bpy if len(sys.argv) > 1: mat_name = sys.argv[2] voronoi_scale = int(sys.argv[4]) else: mat_name = "DefaultMat" voronoi_scale = 300 mat_ref = bpy.data.materials.new(mat_name) # 后续材质创建逻辑... mat_ref.node_tree.nodes["Voronoi Texture"].inputs[2].default_value = voronoi_scale
2. 通过exec命名空间直接传递参数
这种方式更灵活,无需依赖sys.argv,直接将参数注入被执行代码的运行环境:
import bpy filename = 'C:\\temp\\script.py' script_code = compile(open(filename).read(), filename, 'exec') # 定义要传递的参数,可直接包含bpy模块确保脚本能访问 custom_params = { "mat_name": "Mat from Inject", "voronoi_scale": 400, "bpy": bpy } # 执行时传入自定义命名空间,脚本可直接使用这些变量 exec(script_code, globals(), custom_params)
对应的script.py可以直接使用这些变量:
mat_ref = bpy.data.materials.new(mat_name) mat_ref.use_nodes = True nodes = mat_ref.node_tree.nodes mat_ref.node_tree.links.clear() mat_ref.node_tree.nodes.clear() node_diffuse = nodes.new(type='ShaderNodeBsdfDiffuse') node_matoutput = nodes.new(type='ShaderNodeOutputMaterial') node_voronoi = nodes.new(type='ShaderNodeTexVoronoi') mat_ref.node_tree.links.new(node_diffuse.outputs['BSDF'], node_matoutput.inputs['Surface']) mat_ref.node_tree.links.new(node_voronoi.outputs['Distance'], node_matoutput.inputs['Displacement']) mat_ref.node_tree.nodes["Voronoi Texture"].inputs[2].default_value = voronoi_scale
3. 模拟标准输入(针对使用input()的脚本)
如果脚本需要读取标准输入,可以通过重定向sys.stdin实现:
import sys from io import StringIO filename = 'C:\\temp\\script.py' # 模拟用户输入的内容,每行对应一次input()调用 simulated_input = "MyMaterial\n350\n" original_stdin = sys.stdin sys.stdin = StringIO(simulated_input) exec(compile(open(filename).read(), filename, 'exec')) # 恢复原始输入流 sys.stdin = original_stdin
对应的script.py可以直接用input()获取值:
import bpy mat_name = input("Enter material name: ") voronoi_scale = int(input("Enter Voronoi scale: ")) # 后续材质创建逻辑...
内容的提问来源于stack exchange,提问作者Jebathon
相关产品推荐
相关产品推荐

