【问题标题】:Asynchronous location lookup on GAE/webapp2GAE/webapp2 上的异步位置查找
【发布时间】:2013-07-17 15:01:11
【问题描述】:

我确实有以下要填充的 GAE 数据存储模型 (models/location.py):

from google.appengine.ext import db
class Location(db.Model):
    name = db.StringProperty(required=True)
    country = db.StringProperty(required=False)
    address = db.PostalAddressProperty(required=False)
    coordinates = db.GeoPtProperty(required=False)
    description = db.TextProperty(required=False)

为此,我创建了一个类 LocationCreateHandler 和一个函数 _geocode (handlers/location.py):

from google.appengine.ext import db
from google.appengine.api import urlfetch
from webapp2_extras import json
import urllib
from handlers import BaseHandler
from models.location import Location
import logging

class LocationCreateHandler(BaseHandler):
    def post(self):
        name = self.request.get("name")
        country = self.request.get("country")
        address = self.request.get("address")
        coordinates = _geocode(self, address)
        description = self.request.get("description")
        newLocation = Location(name=name, country=country, address=address, coordinates=coordinates, description=description)
        newLocation.put()
        return self.redirect("/location/create")

    def get(self):
        self.render_response("location/create.html")

def _geocode(self, address):
    try:
        logging.info("Geocode address: %s", address)
        parameter = {'address': address.encode('utf-8'), 'sensor': 'false'}
        payload = urllib.urlencode(parameter)
        url = ('https://maps.googleapis.com/maps/api/geocode/json?%s' % payload)
        logging.info("Geocode URL: %s", url)
        result = urlfetch.fetch(url)
        jsondata = json.decode(result.content)
        location = jsondata['results'][0]['geometry']['location']
        coordinates = '%s,%s' % (location['lat'], location['lng'])
        logging.info("Geocode coordinates: %s", coordinates)
        return coordinates
    except:
        return "0.0,0.0"

我将如何使这个异步?目前,用户必须等到地理编码查找完成。 一旦我完成这项工作,我还计划在更新位置记录后使用 _geocode()。

我仍然需要弄清楚“结果 =”之后的 _geocode 部分,这似乎是一个错误,因为我总是收到 0.0,0.0。

-卢卡。

【问题讨论】:

    标签: json google-app-engine asynchronous webapp2 google-geocoder


    【解决方案1】:

    task queues 似乎很好用。当 POST 到达时,启动一个任务,将 Location 实体的所有参数传递给它。然后,您可以完成请求并立即返回给客户端。该任务可以调用 _geocode,然后使用所有数据创建 Location 实体。

    或者,如果您出于某种原因需要在请求处理程序中创建 Location 对象,您可以在 POST 处理程序中执行此操作,并将新实体的密钥传递给任务。任务完成后,它可以获取实体并使用坐标更新它。

    此外,为了帮助确定您的 urlfetch 无法正常工作的原因,这里有一种方法可以在捕获异常的同时记录异常:

    import traceback
    try:
        ...
    except:
        logging.exception(traceback.print_exc())
    

    【讨论】:

      【解决方案2】:

      谢谢你,杰米

      我现在确实使用任务队列实现了 GeocodeWorker (workers/googleapis.py):

      from handlers import BaseHandler
      import urllib
      import logging
      from google.appengine.api import urlfetch
      from google.appengine.ext import db
      from webapp2_extras import json
      from models.location import Location
      
      class GeocodeWorker(BaseHandler):
          def post(self):
              address = self.request.get('address')
              logging.info("Geocode address: %s", address)
              parameter = {'address': address.encode('utf-8'), 'sensor': 'false'}
              url = ('https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(parameter))
              logging.info("Geocode URL: %s", url)
              result = urlfetch.fetch(url)
              JSONData = json.decode(result.content)
              location = JSONData['results'][0]['geometry']['location']
              coordinates = '%s,%s' % (location['lat'], location['lng'])
              logging.info("Geocode coordinates: %s", coordinates)
              key = self.request.get('key')
              logging.info("Geocode key: %s", key)
              existingLocation = Location.get(db.Key(key))
              existingLocation.coordinates = coordinates
              existingLocation.put()
      

      我还修改了我的位置处理程序 (handlers/location.py) 以调用工作人员:

      from google.appengine.api import taskqueue
      from webapp2 import uri_for
      
      class LocationCreateHandler(BaseHandler):
          def get(self):
              self.render_response('location/create.html')
          def post(self):
              name = self.request.get('name')
              country = self.request.get('country')
              address = self.request.get('address')
              description = self.request.get('description')
              newLocation = Location(name=name, country=country, address=address, description=description)
              key = newLocation.put()
              params = {'key': key, 'address': address}
              taskqueue.add(url=uri_for('googleapis-geocode'), queue_name='googleapis', name=('googleapis-geocode-%s' % key), params=params)
              return self.redirect('/location/create')
      

      我还创建了一个 queue.yaml 文件,定义了 googleapis 队列。 我也删除了 try: except: 部分。 google 队列将在定义的时间后自动重试操作并退出。

      您是否看到任何改进的领域?

      -卢卡。

      【讨论】:

      • 对不起,我一开始没有看到这个。如果有人对您回答的问题发布了另一个答案,Stack Overflow 不会通知您。如果它对你有用,你能接受/赞成我的回答吗?
      • 嗨,杰米,我确实接受了你的回答。它确实做了它应该做的事情。非常感谢!
      猜你喜欢
      • 2012-03-21
      • 2013-06-29
      • 1970-01-01
      • 2015-03-14
      • 2016-11-01
      • 2014-10-03
      • 2012-07-14
      • 2012-02-06
      • 1970-01-01
      相关资源
      最近更新 更多