0

私は django-celery のテスト インスタンスをセットアップし、いくつかの基本的なセロリの例を調べて、奇妙に思われるものに遭遇しました。

最初に、「Django の最初のステップ」セロリのページを調べました: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html

標準的なセロリ チュートリアルの最初のいくつかのセクションの基本的な例と同様に、すべてが正しく機能しました。

python manage.py シェル

Django シェルでいくつかのキャンバス プリミティブを試し始めると、次のように NameError が発生します。

$ python manage.py shell
In [1]: from celerytest.tasks import add
In [2]: from celery import group
In [3]: group(add.s(i, i) for i in xrange(10))().get()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 group(add.s(i, i) for i in xrange(10))().get()
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/celery/canvas.pyc in __call__(self, *partial_args, **options)
    397
    398     def __call__(self, *partial_args, **options):
--> 399         tasks = [task.clone() for task in self.tasks]
    400         if not tasks:
    401             return
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/celery/utils/functional.pyc in __iter__(self)
    286
    287     def __iter__(self):  # needed for Python 2.5
--> 288         return iter(self.data)
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/kombu/utils/__init__.pyc in __get__(self, obj, type)
    292             return obj.__dict__[self.__name__]
    293         except KeyError:
--> 294             value = obj.__dict__[self.__name__] = self.__get(obj)
    295             return value
    296
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/celery/utils/functional.pyc in data(self)
    283     @cached_property
    284     def data(self):
--> 285         return list(self.__it)
    286
    287     def __iter__(self):  # needed for Python 2.5
/Users/jacinda/envs/testproj/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <genexpr>((i,))
----> 1 group(add.s(i, i) for i in xrange(10))().get()
NameError: global name 'add' is not defined

しかし、この次の行は機能します:

In [4]: add.delay(2,2).get()
Out[4]: 4

サブタスクを明示的にリストするように:

In [5]: group([add.s(1,2), add.s(3,4)])().get()
Out[5]: [3, 7]

ipython

manage.py シェルを使用する代わりに、通常の Python シェルを使用して手動で設定をインポートすると、すべてが機能します。いえ

$ ipython
In [1]: from testproj import settings
In [2]: from celerytest.tasks import add
In [3]: from celery import group
In [4]: group(add.s(i, i) for i in xrange(10))().get()
Out[4]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

私は epdb で失敗したケースを見てきましたが、何が起こっているのか正確にはわかりません。

私はこれについてグーグルで検索しましたが、私が見つけた唯一の 100% 類似の参照は、セロリの github ページのこの問題でした: https://github.com/celery/celery/issues/1222。ポスターは私が抱えているのと同じ問題に言及していますが、彼の「Python/Django シェルが何か奇妙なことをしている」とだけ言っており、それ以上詳しく説明していません。これの原因についてのアイデアはありますか、それとも他に見るべき場所があるかどうか

4

2 に答える 2

2

かなりの量の掘り下げの後、問題の原因を突き止めましたが、実際には Django トランクで既に修正されています (ただし、現在使用している 1.5 リリースにはありません)。

Django の shell コマンドは、このように iPython を起動することが判明しました (django/core/management/commands/shell.py 内)。

from IPython import embed
embed()

ただし、関数内でembed()を呼び出すと、iPythonが個別のローカルおよびグローバル名前空間で開始されます( iPython Github Issue 62 )。そのため、ラムダ関数とジェネレーター式 (グループなど) は失敗します。

これを修正するために、iPython は、この副作用のないシェルを開始する別の方法を提供します。

from IPython.frontend.terminal.ipapp import TerminalIPythonApp
app = TerminalIPythonApp.instance()
app.initialize(argv=[])
app.start()

Django の github サイトの差分

これは、今後のバージョン ( Django Issue ) で表示されるはずです。このパッチを 1.5.1 に適用してテストしたところ、適用すると元のコードが正しく動作しました。

于 2013-05-17T21:10:02.450 に答える