奥利维尔的答案很好,也很简洁,但为了我自己的好奇心,我想看看它与更精确的计算相比如何(他们的答案假设网格单元足够小,可以近似为正方形)。
          
          import numpy as np
from pyproj import Geod
from shapely.geometry import LineString, Point, Polygon
lons = np.arange(0,20,0.1)
lats = np.arange(30,45,0.1)
# Fast way, square approx of grid cells
geod = Geod(ellps="WGS84")
lon2D,lat2D = np.meshgrid(lons, lats)
_,_, distEW = geod.inv(lon2D[:,:-1],lat2D[:,1:], lon2D[:,1:], lat2D[:,1:])
_,_, distNS = geod.inv(lon2D[1:,:],lat2D[1:,:], lon2D[1:,:], lat2D[:-1,:])
square_area = distEW[1:,:] * distNS[:,1:]
# Slower way, geodesic areas
def stack_coords(x, y):
    """Stacks coordinate lists into a 2D array of coordinate pairs,
       flattened to list of coordinate pairs"""
    out = np.vstack(np.stack(np.meshgrid(x, y), axis=2))
    return out
def get_lat_squares(lats, lons):
    """Construct shapely Polygons for a single longitude but
       every latitude.
       Area is constant with longitude so just copy results.
    lats_0 = lats[:-1]
    lats_1 = lats[1:]
    lons_0 = lons[0:1]
    lons_1 = lons[1:2]
    c1 = stack_coords(lons_0, lats_0)
    c2 = stack_coords(lons_1, lats_0)
    c3 = stack_coords(lons_1, lats_1)
    c4 = stack_coords(lons_0, lats_1)
    squares = []
    for p1, p2, p3, p4 in zip(c1, c2, c3, c4):
        squares.append(Polygon([p1, p2, p3, p4]))
    return squares
def get_areas(lats, lons):
    squares = get_lat_squares(lats, lons)
    geod = Geod(ellps="WGS84")
    areas = []
    for square in squares:
        area = geod.geometry_area_perimeter(square)[0]
        areas.append(area)
    return np.array(areas)
geodesic_areas = get_areas(lats, lons)
for a1, a2 in zip(geodesic_areas, square_area[:,0]):
   print(a1, a2)
Output:
106904546.2618103 106850809.52460858
106798611.31295013 106744711.14938568
106692351.02400208 106638287.58503169
106585765.66596985 106531539.10307406
106478855.51091766 106424465.9760592
88300037.70746613 88224423.89253764