我正在获取GZipped LXML文件并尝试将产品条目写入数据库模型。以前我遇到了本地内存问题,这些问题是通过SO(question)的帮助解决的。现在我把一切都工作并部署了,但是在服务器上我得到以下错误:
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
根据Paul的建议,我实施了后端。经过一些麻烦后,它就像一个魅力 - 找到我在下面使用的代码。
我的backends.yaml看起来如下:
backends:
- name: mybackend
instances: 10
start: mybackend.app
options: dynamic
我的app.yaml如下:
handlers:
- url: /update/mybackend
script: mybackend.app
login: admin
答案 0 :(得分:2)
后端就像前端实例,但它们不能扩展,您必须在需要时停止并启动它们(或将它们设置为动态,这可能是您最好的选择)。
您可以在后端拥有高达1024MB的内存,因此它可能适用于您的任务。
https://developers.google.com/appengine/docs/python/backends/overview
App Engine后端是您的应用程序的实例,它们可以免于请求截止日期,并且可以访问比正常实例更多的内存(最大1GB)和CPU(最高4.8GHz)。它们专为需要更快性能,大量可寻址内存以及连续或长时间运行的后台进程的应用程序而设计。后端有多种尺寸和配置,并且需要正常运行而不是CPU使用。
后端可以配置为常驻或动态。居民 后端连续运行,让你依赖于他们的状态 内存随时间推移并执行复杂的初始化动态后端 当他们收到请求时就会存在,并被拒绝 闲置时;它们非常适合间歇性或受其驱动的工作 用户活动。有关两者之间差异的更多信息 驻留和动态后端,请参阅后端类型以及 讨论启动和关机。
听起来就像你需要的一样。免费使用级别也适用于您的任务。
答案 1 :(得分:0)
关于后端:查看您提供的示例 - 看起来您的请求只是由前端实例处理。
要让它由后端处理,请尝试调用以下任务:http://mybackend.my_app_app_id.appspot.com/update/mybackend
另外,我认为您可以从start: mybackend.app
backends.yaml