How do I split the edges on all objects in a scene with a script? I want to create a script that opens a blender file and splits the edges of all objects in it, perhaps ignoring those that are specified as smooth.

This is for a custom renderer that takes in blend files but interpolates ALL mesh normals from its vertices, which makes it difficult to have walls when they have a volume (i.e. their vertex normals don't match any of their faces).

It should be pretty straightforward, but blender's API comes off as strange to me, and I don't quite get the best way of doing things.

This is what I've got

import bpy
import sys

scene_file = sys.argv[sys.argv.index('--')+1]

bpy.ops.wm.open_mainfile(filepath=scene_file)
bpy.ops.object.select_all(action='DESELECT')

for i in bpy.data.objects:
    i.select = True
    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.edge_split()
    bpy.ops.object.editmode_toggle()

bpy.ops.wm.save_mainfile(filepath=scene_file[:-5]+'modded.blend')


I'm kind of trying to emulate the steps I'd take on the GUI, go through every object, get into edit mode, select all vertices/faces/edges, split edges, exit edit mode and continue. But it doesn't seem to do what I want (or anything in fact).

I've also seen the bmesh.ops.split_edges(bm, edges, verts, use_verts) operator, but it requires mesh, edges and vertices, which I don't know how to retrieve from the object.

Also, I may want to make all normals consistent before splitting them just in case.
Using bmesh.ops.split_edges(..)

Test script, object mode, for all unique meshes of all mesh objects in the scene, load a bmesh, split all edges, rewrite to mesh.  Need only pass edges of the bmesh to the operator. 

import bpy
import bmesh
context = bpy.context
scene = context.scene

bm = bmesh.new()
meshes = set(o.data for o in scene.objects if o.type == 'MESH')
for me in meshes:
    bm.from_mesh(me)
    bmesh.ops.split_edges(bm, edges=bm.edges)
    bm.to_mesh(me)
    bm.clear() 

bm.free()    


On smooth shading AFAIK it is set on a per face basis. Using the methods outlined here Using python to set object shading to &#39;smooth&#39; could make a flag to check if any, or in this case all the faces have smooth shading.

# check if all faces in bmesh are smooth
is_smooth = all(f.smooth for f in bm.faces)


Some notes on question code:

when using operators its far better to iterate over context.scene.objects or if pre selected context.selected_objects.  The collection bpy.data.objects is all objects in the blend whether linked to context scene any scene or no scene.  As well as being selected you also want to set the object to active, and select all geom before calling operator

mesh_objects = [o for o in context.scene.objects if o.type == 'MESH']
meshes = set(o.data for o in mesh_objects)
for ob in mesh_objects:
    if not meshes:
        break
    elif ob.data not in meshes:  
        continue
    context.scene.objects.active = ob
    ob.select = True
    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.edge_split()
    bpy.ops.object.editmode_toggle()
    meshes.remove(ob.data)


Note that 100 objects in a scene could share one mesh, hence the logic above to avoid calling the operator on the same mesh 100 times. 

No biggy, but as a generality, i is used for integer iterators.