GZipped LXMLファイルをフェッチして、ProductエントリをDatabseモデルに書き込もうとしています。以前、私はローカルメモリの問題を抱えていましたが、SOのヘルプによって解決されました(質問)。これですべてが機能し、デプロイされましたが、サーバーで次のエラーが発生します。
Exceeded soft private memory limit with 158.164 MB after servicing 0 requests total
今、私はメモリ使用量を減らすために私が知っているすべてを試し、現在以下のコードを使用しています。Gzip圧縮されたファイルは約7MBですが、解凍されたファイルは80MBです。ローカルでは、コードは正常に機能しています。Cron Jobと同様にHTTPリクエストとして実行してみましたが、違いはありませんでした。今、私はそれをより効率的にする方法があるかどうか疑問に思っています。
SOに関するいくつかの同様の質問は、私がよく知らないフロントエンドとバックエンドの仕様に言及していました。私はGAEの無料バージョンを実行していますが、このタスクは週に1回実行する必要があります。前進するための最善の方法に関する提案をいただければ幸いです。
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