我正在获取 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上的一些类似问题参考了我不熟悉的前端和后端规范。我正在运行 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