Not sure is there has a convenient function in blender api to do this. But my idea is separate by Loose Parts to single object and for every object duplicated, find the correct order of the vertices. finally delete them and restore the select data.
Suppose the object is:

First, do the separate function. You can use
bpy.ops.mesh.separate(type='LOOSE')
to achieve.
here is the function, it will return the objects are separated.
# Suppose in Object mode, and the object selected
import bpy, bmesh
def separate_obj():
context_obj_old = bpy.context.object
data_objects_old = [obj for obj in bpy.data.objects]
old_selected = bpy.context.selected_objects
for obj in old_selected:
obj.select_set(False)
bpy.context.object.select_set(True)
bpy.ops.object.duplicate()
object_duplicated = bpy.context.object
bpy.ops.object.mode_set(mode = 'EDIT')
obj = bpy.context.object
me = obj.data
bm = bmesh.from_edit_mesh(me)
verts = bm.verts
edges = bm.edges
verts.ensure_lookup_table()
bm.select_mode |= {'VERT'}
bm.select_flush_mode()
# deslect all
for v in verts:
v.select_set(False)
while verts:
# select first vert
verts[0].select_set(True)
bpy.ops.mesh.select_linked(delimit=set())
bmesh.update_edit_mesh(me)
bpy.ops.mesh.separate(type='SELECTED')
verts.ensure_lookup_table()
bpy.ops.object.mode_set(mode = 'OBJECT')
islands = [obj for obj in bpy.data.objects if obj not in data_objects_old and obj != object_duplicated]
for i in islands:
i.select_set(False)
object_duplicated.select_set(True)
bpy.ops.object.delete(use_global=True, confirm=False)
for obj in old_selected:
obj.select_set(True)
bpy.context.view_layer.objects.active = context_obj_old
return islands
islands = separate_obj()
print(islands)
print("")

next step is find the correct order of vertices for every objects
Full code
# Suppose in Object mode, and the object selected
import bpy, bmesh
def separate_obj():
context_obj_old = bpy.context.object
data_objects_old = [obj for obj in bpy.data.objects]
old_selected = bpy.context.selected_objects
for obj in old_selected:
obj.select_set(False)
bpy.context.object.select_set(True)
bpy.ops.object.duplicate()
object_duplicated = bpy.context.object
bpy.ops.object.mode_set(mode = 'EDIT')
obj = bpy.context.object
me = obj.data
bm = bmesh.from_edit_mesh(me)
verts = bm.verts
edges = bm.edges
verts.ensure_lookup_table()
bm.select_mode |= {'VERT'}
bm.select_flush_mode()
# deslect all
for v in verts:
v.select_set(False)
while verts:
# select first vert
verts[0].select_set(True)
bpy.ops.mesh.select_linked(delimit=set())
bmesh.update_edit_mesh(me)
bpy.ops.mesh.separate(type='SELECTED')
verts.ensure_lookup_table()
bpy.ops.object.mode_set(mode = 'OBJECT')
islands = [obj for obj in bpy.data.objects if obj not in data_objects_old and obj != object_duplicated]
for i in islands:
i.select_set(False)
object_duplicated.select_set(True)
bpy.ops.object.delete(use_global=True, confirm=False)
for obj in old_selected:
obj.select_set(True)
bpy.context.view_layer.objects.active = context_obj_old
return islands
islands = separate_obj()
print(islands)
print("")
# -- store selected data
context_obj_old = bpy.context.object
old_selected = bpy.context.selected_objects
for obj in old_selected:
obj.select_set(False)
# -- store selected data END
list_coords = []
for obj in islands:
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode = 'EDIT')
me = obj.data
bm = bmesh.from_edit_mesh(me)
verts = bm.verts
edges = bm.edges
verts.ensure_lookup_table()
edges.ensure_lookup_table()
bm.select_mode |= {'VERT'}
bm.select_flush_mode()
# deslect all
for v in verts:
v.select_set(False)
bm.select_mode |= {'EDGE'}
bm.select_flush_mode()
coords = []
first_edge = None
if edges:
for e in edges:
l0 = len(e.verts[0].link_edges)
l1 = len(e.verts[1].link_edges)
if l0 > 2 or l1 > 2:
first_edge = False
break
if l0 == 1 or l1 == 1:
first_edge = e
break
if first_edge is None: # means closed path
first_edge = edges[0]
elif first_edge is False: # complex path
list_coords.append(coords)
bpy.ops.object.mode_set(mode = 'OBJECT')
continue
p1 = first_edge.verts[0]
p2 = first_edge.verts[1]
if len(p1.link_edges) != 1:
p1, p2 = p2, p1
link_edges = p2.link_edges
len_link = len(link_edges)
if len_link > 2: # complex path
list_coords.append(coords)
bpy.ops.object.mode_set(mode = 'OBJECT')
continue
elif len_link == 1:
list_coords.append([*p1.co], [*p2.co])
bpy.ops.object.mode_set(mode = 'OBJECT')
continue
if link_edges[1] == first_edge:
next_edge = link_edges[0]
else:
next_edge = link_edges[1]
coords.append([*p1.co])
coords.append([*p2.co])
# print(p1.co)
# print(p2.co)
all_edges = [e for e in edges]
all_edges.remove(first_edge)
while all_edges:
p1 = p2
first_edge = next_edge
# print(p1.co, first_edge.verts[0].co, first_edge.verts[1].co)
if p1 == first_edge.verts[0]:
p2 = first_edge.verts[1]
else:
p2 = first_edge.verts[0]
# print(p2.co)
link_edges = p2.link_edges
len_link = len(link_edges)
if len_link > 2: # complex path
coords.clear()
break
elif len_link == 1:
coords.append([*p2.co])
break
if link_edges[1] == first_edge:
next_edge = link_edges[0]
else:
next_edge = link_edges[1]
coords.append([*p2.co])
all_edges.remove(first_edge)
else:
# one vert only
verts.ensure_lookup_table()
coords.append(verts[0].co.copy())
list_coords.append(coords)
bpy.ops.object.mode_set(mode = 'OBJECT')
for obj in islands:
obj.select_set(True)
bpy.ops.object.delete(use_global=True, confirm=False)
# -- restore selected data
for obj in old_selected:
obj.select_set(True)
bpy.context.view_layer.objects.active = context_obj_old
# -- restore selected data END
print("### This is local space ###")
for coords in list_coords:
print("[")
for v in coords:
print(" ",v)
print("]")
print("")
if list_coords[0][0] == list_coords[0][-1]:
print("list in index 0 is closed path, else it has two vertices on the same position")
else:
print("list in index 0 is not closed path")
print("-- END --")
And the result
