11

最近、アプリケーションの 1 つにセロリ(より具体的にはdjango-celery ) を統合しました。次のようにアプリケーションにモデルがあります。

class UserUploadedFile(models.Model)
    original_file = models.FileField(upload_to='/uploads/')    
    txt = models.FileField(upload_to='/uploads/')
    pdf = models.FileField(upload_to='/uploads/')
    doc = models.FileField(upload_to='/uploads/')
    
    def convert_to_others(self):
        # Code to convert the original file to other formats

ここで、ユーザーがファイルをアップロードしたら、元のファイルを txt、pdf、および doc 形式に変換したいと考えています。メソッドの呼び出しはconvert_to_others少し高価なプロセスなので、セロリを使用して非同期で行う予定です。だから私は次のように簡単なセロリタスクを書きました。

@celery.task(default_retry_delay=bdev.settings.TASK_RETRY_DELAY)
def convert_ufile(file, request):
    """ 
    This task method would call a UserUploadedFile object's convert_to_others
    method to do the file conversions.

    The best way to call this task would be doing it asynchronously
    using apply_async method.
    """
    try:
        file.convert_to_others()
    except Exception, err:
        # If the task fails log the exception and retry in 30 secs
        log.LoggingMiddleware.log_exception(request, err)
        convert_ufile.retry(exc=err)
    return True

次に、次のようにタスクを呼び出します。

ufile = get_object_or_404(models.UserUploadedFiles, pk=id)
tasks.convert_ufile.apply_async(args=[ufile, request])

apply_asyncメソッドが呼び出されると、次の例外が発生します。

PicklingError: Can't pickle <type 'cStringIO.StringO'>: attribute lookup cStringIO.StringO failed

pickleこれは、セロリ(デフォルト)がライブラリを使用してデータをシリアル化し、ピクルがバイナリファイルをシリアル化できないためだと思います。

質問

バイナリ ファイルを単独でシリアライズできるシリアライザーは他にありますか? そうでない場合、デフォルトのシリアライザーを使用してバイナリファイルをシリアル化するにはどうすればよいpickleですか?

4

1 に答える 1

7

セロリは、ピクルがサポートされていないデータをピクルしようとするのは正しいです。セロリタスクに送信したいデータをシリアル化する方法を見つけたとしても、私はこれをしません。

セロリ タスクに送信するデータはできるだけ少なくすることを常にお勧めします。そのため、あなたの場合はUserUploadedFileインスタンスの ID のみを渡します。これがあれば、セロリタスクでIDでオブジェクトをフェッチし、 convert_to_others()を実行できます。

また、タスクが実行される前に、オブジェクトの状態が変わる (または削除される) 可能性があることにも注意してください。そのため、オブジェクトの完全なコピーを送信するよりも、セロリ タスクでオブジェクトをフェッチする方がはるかに安全です。

要約すると、インスタンス ID のみを送信し、それをタスクで再フェッチすると、いくつかのことが得られます。

  • キューに送信するデータが少なくなります。
  • データの不整合の問題に対処する必要はありません。
  • あなたの場合、実際に可能です。:)

唯一の「欠点」は、データを再取得するために追加の安価な SELECT クエリを実行する必要があることです。これは、上記の問題と比較すると、全体的にはかなりのように見えますね。

于 2013-01-15T19:31:25.240 に答える