#背景
pythonアプリでメッセージキューイングを利用したい。そこでRabbitMQ+Celeryを選択したが、環境の都合によりcallerはPython2でworkerは3で動かしている。
#環境
Linux Mint 17
Python:callerは2.7.6(Mint標準)、workerは3.5.2
RabbitMQ:3.2.4-1
celery:4.0.2
#困ったこと
Celeryのチュートリアルには、タスクを呼ぶ為にはcaller側でもタスクを定義したモジュールをインポートしろとある。ところがインポートすると、callerとworkerのPythonのバージョンの違いにより、エラーになる。
tasks.py
from celery import Celery
celery.config_from_object('celeryconfig')
@celery.task
def add(x, y):
return x + y
caller.py
from tasks import add #ここでエラーになる/そもそもファイルが見えない
add.delay(4, 4)
#おかしいな
callerとworkerの間には当然brokerが介在し、amqpというプロトコルで通信する。今回は同一ホストだが、リモートでも分散環境でも対応しているはず。そういう環境ではインポート出来るとは限らんやんね?そもそも何故インポートしている?メソッドシグネチャの読み取り?
#結論を早く言え
タスク名を文字列で渡せるメソッドがありました。引数はapply_asyncと同じだそうです。
caller.py(改)
from celery import Celery
celery.config_from_object('celeryconfig')
result =celery.send_task('add', (4, 4), queue = 'hayosei')
result.get(timeout = 1000)
#注意点
メソッド名=タスク名であってもタスク名の定義は必須。workerにそんなタスクは知らんと言われたらチェック。
tasks.py(改)
from celery import Celery
celery.config_from_object('celeryconfig')
@celery.task(name='add')
def add(x, y):
return x + y
#参考サイト
python - Celery - How to send task from remote machine? - Stack Overflow
correct task definitions when using tasks by name.
公式の説明