I have a project that creates a 3D object with vertex colours and saves it as blenderObj.obj. I have a Python script using bpy called "blenderConverter.py" which modifies the 3D object, bakes its vertex colours into a texture image and exports both.
When I run blenderConverter.py in the IDE, it works fine, but when I try to run it in my Flask server, I get this error:
Traceback (most recent call last):
File "*path*\lib\site-packages\flask\app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
File "*path*\lib\site-packages\flask\app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
File "*path*\lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
File "*path*\lib\site-packages\flask\app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "*path*\flaskServer.py", line 11, in start
convert()
File "C*path*\blenderConverter.py", line 11, in convert
bpy.ops.wm.obj_import(files=files)
File "*path*\lib\site-packages\bpy\3.5\scripts\modules\bpy\ops.py", line 113, in __call__
ret = _op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.wm.obj_import.poll() failed, context is incorrect
flaskServer.py executes the convert() function of blenderConverter.py on a route.
blenderConverter.py looks like this:
import bpy
def convert():
# Wipe Scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# Import .obj
files = [{"name": "blenderObj.obj"}]
bpy.ops.wm.obj_import(files=files)
# Rotate and Scale .obj
obj = bpy.context.selected_objects[0]
obj.rotation_euler = (0, 0, 0)
obj.scale = (5, 5, 5)
# Add new Material to .obj
bpy.ops.material.new()
material = bpy.data.materials[-1]
obj.data.materials.append(material)
# Configure Material
node_tree = material.node_tree
bsdf = node_tree.nodes[0]
color_attribute = node_tree.nodes.new(type="ShaderNodeVertexColor")
color_attribute.layer_name = "Color"
node_tree.links.new(color_attribute.outputs["Color"], bsdf.inputs["Base Color"])
# Configure Bake
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.cycles.device = 'GPU'
scene.render.bake.use_pass_indirect = False
scene.render.bake.use_pass_direct = False
scene.cycles.bake_type = 'DIFFUSE'
scene.render.bake.margin = 5
# Prepare image
image_texture = node_tree.nodes.new(type="ShaderNodeTexImage")
image = bpy.data.images.new('bake', 1024, 1024)
image_texture.image = image
# Create UV Map
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.smart_project(angle_limit=66, island_margin=0.002)
bpy.ops.object.editmode_toggle()
# Bake
node_tree.nodes.active = image_texture
bpy.context.view_layer.objects.active = obj
bpy.ops.object.bake(type='DIFFUSE', save_mode='EXTERNAL')
# Save image
image.filepath_raw = '//dispatch//bake.png'
image.file_format = "PNG"
image.save()
# Save .obj
bpy.ops.export_scene.obj(filepath='dispatch/object.obj', use_materials=False)
Through some research I got it working by using os.system("blender -b --python blenderConverter.py") instead of calling convert() on the Flask server. But this does not seem to be a best practice?
I also found that you can build blender as a python module, but that did not solve my problem. It could be my fault if I build it wrong or something.
My goal is to run blenderConverter without a Blender instance in the background.
Since I am pretty new to Python or Flask or Blender, I do not know what best practices are or are not. Is the os.system() solution ok or should I try to find a way to use convert()? If anyone can help I would appreciate it.
I am happy to help if more context or information is needed.