Issue
I'm trying to create a celery task for uploading and resizing an image before storing it to Amazon S3. But it doesn't work as expected. Without the task everything is working fine. This is the code so far:
stacktrace
Traceback (most recent call last):
File "../myVE/lib/python2.7/site-packages/kombu/messaging.py", line 579, in _receive_callback
decoded = None if on_m else message.decode()
File "../myVE/lib/python2.7/site-packages/kombu/transport/base.py", line 147, in decode
self.content_encoding, accept=self.accept)
File "../myVE/lib/python2.7/site-packages/kombu/serialization.py", line 187, in decode
return decode(data)
File "../myVE/lib/python2.7/site-packages/kombu/serialization.py", line 74, in pickle_loads
return load(BytesIO(s))
File "../myVE/lib/python2.7/site-packages/werkzeug/datastructures.py", line 2595, in __getattr__
return getattr(self.stream, name)
File "../myVE/lib/python2.7/site-packages/werkzeug/datastructures.py", line 2595, in __getattr__
return getattr(self.stream, name)
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
views.py
from PIL import Image
from flask import Blueprint, redirect, render_template, request, url_for
from myapplication.forms import UploadForm
from myapplication.tasks import upload_task
main = Blueprint('main', __name__)
@main.route('/upload', methods=['GET', 'POST'])
def upload():
form = UploadForm()
if form.validate_on_submit():
upload_task.delay(form.title.data, form.description.data,
Image.open(request.files['image']))
return redirect(url_for('main.index'))
return render_template('upload.html', form=form)
tasks.py
from StringIO import StringIO
from flask import current_app
from myapplication.extensions import celery, db
from myapplication.helpers import resize, s3_upload
from myapplication.models import MyObject
@celery.task(name='tasks.upload_task')
def upload_task(title, description, source):
stream = StringIO()
target = resize(source, current_app.config['SIZE'])
target.save(stream, 'JPEG', quality=95)
stream.seek(0)
obj = MyObject(title=title, description=description, url=s3_upload(stream))
db.session.add(obj)
db.session.commit()
Solution
It looks like you are attempting to pass the entire uploaded file as part of the Celery message. I imagine that is causing you some trouble. I would recommend seeing if you can save the file to the web server as part of the view, then have the message (the "delay" argument) contain the filename rather than entire file's data. The task can then read the file in from the hard drive, upload to s3, then delete it locally.
Answered By - Mark Hildreth
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.