I propose to use a kdtree so that we'll have an efficient search tree over the UV Map, for all the coordinates you have in input.
The principle is the following:
- Create a kdtree and populate it with UV coordinates
- Initialize it
- Search on it from the input coordinates you have
- From this index, get the corresponding vertex index (in the 3D mesh) using the loops
The tree is initialized once per mesh and allows multiple searches.
The commented code:
import bpy
import bmesh
from mathutils import Vector
from mathutils.kdtree import KDTree
print( '-------------------------------' )
# Do all that in object mode
bpy.ops.object.mode_set(mode = 'OBJECT')
# Get the mesh
obj = bpy.context.active_object
# Get its UV map
uvmap = obj.data.uv_layers['UVMap']
# Make an array of uv coordinates in 3D
coordinates = [(d.uv.x, d.uv.y, 0) for d in uvmap.data]
# Create a jd tree from that
kd = KDTree( len( coordinates ) )
# Populate it
for i, v in enumerate( coordinates ):
kd.insert( v, i )
# Initialize it
kd.balance()
# Input UV coordinates
x = 0.41
y = 0.96
# Search
coordinate, index, distance = kd.find( (x, y, 0) )
print( coordinate )
print( index )
print( distance )
# Corresponding vertex (in the mesh) and its index
vertex_index = obj.data.loops[index].vertex_index
vertex = obj.data.vertices[vertex_index]
print( vertex.index )

Note: there is also a bvhtree version in the blend file. If you have time you could compare the results and perfomence
The main diff between bvh and kd is that bvh will test on faces and kd will test on vertex proximity (so this can be outside the face).
I don't know what is important in your context.
In the blend file, there is two script in the text editor 'KDTree' and 'BVHTree' so that you can choose.