If you want this to be fast and you have a large number of lat/longs to check I highly recommend using postgresql/PostGIS. However it is possible to do this in python, provided you have OGR/GDAL packages installed properly.
Here is an outline of how you might do this purely in python, assuming you have OGR/GDAL packages properly installed (these installations can be non-trivial, so beware)
from osgeo import ogr
#Assumes your points and shapefile are already in the same datum/projection
shapefile_name = "census_tracts.shp"
#This version takes a long_lat_list of the form below and a shapefile name
def getCensusTracts(long_lat_list, shapefile_name):
driver = ogr.GetDriverByName("ESRI Shapefile")
dataSource = driver.Open(shapefile_name, 0)
layer = dataSource.GetLayer()
results_dict = {}
i = 0
for feature in layer:
geom = feature.GetGeometryRef()
i += 1
for pt in long_lat_list:
gid = pt[0]
lon = pt[1]
lat = pt[2]
point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(lon, lat)
if point.Within(geom) == True:
feat_id = feature.GetField("fips")
if gid in results_dict and feat_id not in results_dict[gid]:
results_dict[gid].append(feat_id)
else:
results_dict[gid] = [feat_id]
for pt in long_lat_list:
gid = pt[0]
lon = pt[1]
lat = pt[2]
if gid not in results_dict:
results_dict[gid] = ['NA']
return results_dict
#Where elements are [id, long, lat]
long_lat_list = [[1, -87.5, 35.5],[2, -78.446, 41.353]]
results_dict = getCensusTracts(long_lat_list, shapefile_name)
#results_dict returns a dictionary where {'id: list_of_fips_codes}
print results_dict
Edit: Given Selah's comments I discovered that you cannot iterate over a layer multiple times in OGR. I rewrote the solution so that the census shapefile only need be iterated over once.