【问题标题】:Celery Tutorial Works Correctly in standard iPython shell but not when using Django's embedded iPython shellCelery 教程在标准 iPython shell 中正常工作,但在使用 Django 的嵌入式 iPython shell 时不能正常工作
【发布时间】:2013-05-12 05:18:18
【问题描述】:

我一直在设置 django-celery 的测试实例并浏览了一些基本的 celery 示例,并遇到了一些看起来很奇怪的东西。

我首先在这里浏览了“使用 Django 的第一步”芹菜页面:http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html

一切正常,标准 celery 教程前几节中的基本示例也是如此。

python manage.py shell

当我开始在 Django shell 中尝试一些画布原语时,我得到一个 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

如果我使用常规 Python shell 并手动导入设置而不是使用 manage.py shell,一切正常。即

$ 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 的失败案例,但无法弄清楚到底发生了什么。

我已经在 Google 上搜索过,我发现的唯一 100% 相似的参考是 celery 的 github 页面上的这个问题:https://github.com/celery/celery/issues/1222。海报提到了我遇到的同样问题,但只说他的“Python/Django shell 正在做一些奇怪的事情”,并没有进一步详细说明。关于导致此问题的原因或我应该寻找其他地方的任何想法?

【问题讨论】:

    标签: python django celery django-celery django-shell


    【解决方案1】:

    经过大量挖掘,我找到了问题的根源,实际上它已经在 Django 主干上修复了(虽然它不在当前的 1.5 版本中,但我正在使用它)。

    原来Django的shell命令是这样启动iPython的(在django/core/management/commands/shell.py中)

    from IPython import embed
    embed()
    

    但是,在函数内部调用 embed() 会导致 iPython 以单独的本地和全局命名空间 (iPython Github Issue 62) 开始。所以 lambda 函数和生成器表达式(如 group)失败。

    为了解决这个问题,iPython 提供了一种不同的启动 shell 的方法,它没有这种副作用。

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

    Diff on Django's github site

    这应该会出现在即将发布的版本中 (Django Issue)。我测试了这个应用于 1.5.1 的补丁,我的原始代码在应用后可以正常工作。

    【讨论】:

      【解决方案2】:

      这也发生在我身上,但仅限于使用 ipython/django shell 时。如果 Django 使用默认 shell 或 bpython 一切正常。

      因此,如果您现在想绕过该问题,我建议您使用替代 shell(我使用 bpython)。如果您使用的是虚拟环境:

      $ pip install bpython
      

      【讨论】:

      • 有趣。但奇怪的是,导致问题的具体是 Django/iPython 组合(如上,直接 iPython 手动导入设置文件可以正常工作)。我真的很想弄清楚首先导致问题的区别是什么。有什么想法吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 2011-01-07
      • 1970-01-01
      • 2015-03-27
      • 2013-10-20
      • 1970-01-01
      • 2012-06-01
      相关资源
      最近更新 更多