繁体   English   中英

GAE Python LXML - 超出软私有内存限制

[英]GAE Python LXML - Exceeded soft private memory limit

我正在获取GZipped LXML文件并尝试将产品条目写入数据库模型。 以前我有本地内存问题,这是通过SO( 问题 )的帮助解决的。 现在我把一切都工作并部署了,但是在服务器上我收到以下错误:

Exceeded soft private memory limit with 158.164 MB after servicing 0 requests total

现在我尝试了所有我知道的减少内存使用量,目前正在使用下面的代码。 GZipped文件大约7 MB,而解压缩它是80 MB。 本地代码工作正常。 我尝试将其作为HTTP请求以及Cron Job运行,但它没有任何区别。 现在我想知道是否有任何方法可以提高效率。

关于SO的一些类似问题涉及Frontend和Backend规范,我不熟悉。 我正在运行GAE的免费版本,这项任务必须每周运行一次。 任何关于前进的最佳方式的建议都将非常感激。

from google.appengine.api.urlfetch import fetch
import gzip, base64, StringIO, datetime, webapp2
from lxml import etree
from google.appengine.ext import db

class GetProductCatalog(webapp2.RequestHandler):
  def get(self):
    user = XXX
    password = YYY
    url = 'URL'

    # fetch gziped file
    catalogResponse = fetch(url, headers={
        "Authorization": "Basic %s" % base64.b64encode(user + ':' + password)
    }, deadline=10000000)

    # the response content is in catalogResponse.content
    # un gzip the file
    f = StringIO.StringIO(catalogResponse.content)
    c = gzip.GzipFile(fileobj=f)
    content = c.read()

    # create something readable by lxml
    xml = StringIO.StringIO(content)

    # delete unnecesary variables
    del f
    del c
    del content

    # parse the file
    tree = etree.iterparse(xml, tag='product')

    for event, element in tree:
        if element.findtext('manufacturer') == 'New York':
            if Product.get_by_key_name(element.findtext('sku')):
                    coupon = Product.get_by_key_name(element.findtext('sku'))
                    if coupon.last_update_prov != datetime.datetime.strptime(element.findtext('lastupdated'), "%d/%m/%Y"):
                        coupon.restaurant_name = element.findtext('name')
                        coupon.restaurant_id = ''
                        coupon.address_street = element.findtext('keywords').split(',')[0]
                        coupon.address_city = element.findtext('manufacturer')
                        coupon.address_state = element.findtext('publisher')
                        coupon.address_zip = element.findtext('manufacturerid')
                        coupon.value = '$' + element.findtext('price') + ' for $' + element.findtext('retailprice')
                        coupon.restrictions = element.findtext('warranty')
                        coupon.url = element.findtext('buyurl')
                        if element.findtext('instock') == 'YES':
                            coupon.active = True
                        else:
                            coupon.active = False
                        coupon.last_update_prov = datetime.datetime.strptime(element.findtext('lastupdated'), "%d/%m/%Y")
                        coupon.put()
                    else:
                        pass
            else:
                    coupon = Product(key_name = element.findtext('sku'))
                    coupon.restaurant_name = element.findtext('name')
                    coupon.restaurant_id = ''
                    coupon.address_street = element.findtext('keywords').split(',')[0]
                    coupon.address_city = element.findtext('manufacturer')
                    coupon.address_state = element.findtext('publisher')
                    coupon.address_zip = element.findtext('manufacturerid')
                    coupon.value = '$' + element.findtext('price') + ' for $' + element.findtext('retailprice')
                    coupon.restrictions = element.findtext('warranty')
                    coupon.url = element.findtext('buyurl')
                    if element.findtext('instock') == 'YES':
                        coupon.active = True
                    else:
                        coupon.active = False

                    coupon.last_update_prov = datetime.datetime.strptime(element.findtext('lastupdated'), "%d/%m/%Y")
                    coupon.put()
        else:
            pass

        element.clear()

UDPATE

根据保罗的建议,我实施了后端。 经过一些麻烦后,它就像一个魅力 - 找到我下面使用的代码。

我的backends.yaml看起来如下:

backends:
- name: mybackend
  instances: 10
  start: mybackend.app
  options: dynamic

我的app.yaml如下:

handlers:
- url: /update/mybackend
  script: mybackend.app
  login: admin

后端就像前端实例,但它们不能扩展,您必须在需要时停止并启动它们(或将它们设置为动态,这可能是您最好的选择)。

您可以在后端拥有高达1024MB的内存,因此它可能适用于您的任务。

https://developers.google.com/appengine/docs/python/backends/overview

App Engine后端是您的应用程序的实例,它们可以免于请求截止日期,并且可以访问比正常实例更多的内存(最大1GB)和CPU(最高4.8GHz)。 它们专为需要更快性能,大量可寻址内存以及连续或长时间运行的后台进程的应用程序而设计。 后端有多种尺寸和配置,并且需要正常运行而不是CPU使用。

后端可以配置为驻留或动态。 驻留后端持续运行,允许您随着时间的推移依赖其内存状态并执行复杂的初始化。 动态后端在收到请求时就会存在,并在空闲时被拒绝; 它们非常适合间歇性或由用户活动驱动的工作。 有关驻留和动态后端之间差异的更多信息,请参阅后端类型以及启动和关闭的讨论。

这听起来就像你需要的。 免费使用级别也适用于您的任务。

关于后端:查看您提供的示例 - 看起来您的请求只是由前端实例处理。

要使其由后端处理,请尝试调用以下任务: http//mybackend.my_app_app_id.appspot.com/update/mybackend

另外,我认为你可以从你的backends.yaml删除: start: mybackend.app

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM