Bmesh : how do I keep track of vertices in edited topology? I'm trying to write a script to bisect Ngon rectangles, horizontally or vertically, at a given percentage of the distance along their sides. (The sides may consist of more than one edge).

Some of the script involves finding the right edges to cut, and moving the new vertices to the right place, but I hope this is a minimal expression of my problem:

ob = bpy.context.object
me = ob.data
bm = bmesh.new()    
bm.from_mesh(me)

bm.edges.ensure_lookup_table()

e1 = bm.edges[4]
e2 = bm.edges[3]

ret = bmesh.ops.subdivide_edges(bm, edges=[e1], cuts=1)
v1 = ret['geom_inner'][0]

ret = bmesh.ops.subdivide_edges(bm, edges=[e2], cuts=1)
v2 = ret['geom_inner'][0]

bmesh.ops.connect_verts(bm, verts=[v1,v2])

bm.to_mesh(me)
me.update()

bm.free()


(Here, I've hard-coded the edge selections)

The  bmesh.ops.connect_verts(bm,verts = [v1,v2]) generates an error: '..BMVert has been removed..', which is perhaps understandable, but how would I keep track of v1,the vertex generated by the first cut? If I run this snippet without the connect, the vertices appear just fine in the updated mesh, so they are there, somewhere.




I'm in 2.79
The mesh starts in Object Mode (does that make a difference?)
Tag the verts.

As mentioned in the comments could be done via 

bmesh.ops.subdivide_edges(bm, edges=[e1, e2], cuts=1)


in one fell swoop.

When an operator creates new geometry there is a chance any old geom becomes invalid. However the data of the old will match the new, in which case can use the tag or select attribute to advantage.

Make sure to ignore the invalids with How to remove dead BMVerts from a list?

Test script. In edit mode to see what is going on.. Will work same in object mode

import bpy
import bmesh
ob = bpy.context.edit_object
me = ob.data

bm = bmesh.from_edit_mesh(me)

bm.edges.ensure_lookup_table()

e1 = bm.edges[0]
e2 = bm.edges[2]

ret = bmesh.ops.subdivide_edges(bm, edges=[e1], cuts=1)
v1 = ret['geom_inner'][0]
v1.tag = True
ret = bmesh.ops.subdivide_edges(bm, edges=[e2], cuts=1)
v2 = ret['geom_inner'][0]
v2.tag = True

bmesh.ops.connect_verts(bm, 
        verts=[v for v in bm.verts if v.tag and v.is_valid])

bmesh.update_edit_mesh(me)
me.update()


Note  in 2.80 a mesh can be in edit mode in one view, object in another.

On a formatting side, in argument list, space after a comma, none around equals.