Mapreduce '/manage.py runserver';芹菜映射/减少任务运行时重新启动;有时会引发内部运行错误

Mapreduce '/manage.py runserver';芹菜映射/减少任务运行时重新启动;有时会引发内部运行错误,mapreduce,celery,fabric,django-celery,hadoop-streaming,Mapreduce,Celery,Fabric,Django Celery,Hadoop Streaming,我在django项目中有一个视图,它启动了芹菜任务。芹菜任务本身通过subprocess/fabric触发了一些map/reduce作业,hadoop作业的结果存储在磁盘上——实际上数据库中没有存储任何内容。hadoop作业完成后,芹菜任务发送一个django信号,表示它已经完成,如下所示: #tasks.py 从模型导入MyModel 输入信号 从fabric.operations导入本地 来自芹菜。任务导入任务 类Hadoop化(任务): def运行(自我、我的型号、其他参数): my_mo

我在django项目中有一个视图,它启动了芹菜任务。芹菜任务本身通过subprocess/fabric触发了一些map/reduce作业,hadoop作业的结果存储在磁盘上——实际上数据库中没有存储任何内容。hadoop作业完成后,芹菜任务发送一个django信号,表示它已经完成,如下所示:

#tasks.py
从模型导入MyModel
输入信号
从fabric.operations导入本地
来自芹菜。任务导入任务
类Hadoop化(任务):
def运行(自我、我的型号、其他参数):
my_model=MyModel.objects.get(pk=my_model\u id)
self.hadoopify_函数(我的_模型,其他_参数)
信号。完成信号。发送(
发送方=自身,
my_model_id=my_model_id,
完成=正确,
)
def hadoopify_函数(self、my_模型、其他_参数):
本地(““”hadoop jar/usr/lib/hadoop/hadoop-streaming.jar-D mapred.reduce.tasks=0-文件hadoopify.py-mapper“parse_mapper.py 0 0”-input/user/me/input.csv-output/user/me/output.csv”“)
真正让我困惑的是,当芹菜任务运行时,django runserver正在重新加载,就好像我在django项目中的某个地方更改了一些代码(我可以向您保证,我没有这样做!)。有时,这甚至会在runserver命令中导致错误,在runserver命令重新加载之前,我会看到如下输出,并且再次正常(注意:此错误消息与错误消息非常类似)

由启动的线程中未处理的异常 sys.excepthook中出错: 回溯(最近一次呼叫最后一次): 文件“/usr/lib/python2.6/dist packages/apport\u python\u hook.py”,第48行,apport\u excepthook 如果未启用(): TypeError:“非类型”对象不可调用 最初的例外是: 回溯(最近一次呼叫最后一次): 文件“/home/rdm/Biz/Projects/Daegis/Server_Development/tar/env/lib/python2.6/site packages/django/core/management/commands/runserver.py”,第60行,在内部运行 运行(地址、int(端口)、处理程序) 文件“/home/rdm/Biz/Projects/Daegis/Server_Development/tar/env/lib/python2.6/site packages/django/core/servers/basehttp.py”,第721行,正在运行 httpd.永远为你服务() 文件“/usr/lib/python2.6/SocketServer.py”,第224行,在serve\u中 r、 w,e=select.select([self],[],poll\u interval) AttributeError:“非类型”对象没有属性“选择” 通过将
local(““hadoop…”)替换为
local(“ls”)
,我将问题缩小到何时调用hadoop,这不会导致重新加载django runserver出现任何问题。hadoop代码中没有bug——当它没有被芹菜调用时,它自己运行得很好


你知道是什么原因造成的吗?

我猜芹菜和织物的名字都有冲突。我建议使用更像:

import celery
class Hadoopification(celery.task.Task):
    ...
如果预感好的话,尽量避免任何进一步的碰撞


但事实上,fabric的local非常有趣,本质上只是一个子进程.Popen,您可以尝试调用raw来分离除python stdlib之外的任何内容。

因此在深入研究fabric源代码后,我了解到django正在重新加载,因为我的芹菜任务在fabric.operations.local命令中运行,失败(在hadoop输出puke fest中很难检测到)。当fabric.operations.local命令失败时,导致芹菜死亡,django尝试重新加载。此错误可以通过在hadoop任务中捕获以下内容来检测:

类Hadoop化(任务):
def运行(自我、我的型号、其他参数):
my_model=MyModel.objects.get(pk=my_model\u id)
self.hadoopify_函数(我的_模型,其他_参数)
信号。完成信号。发送(
发送方=自身,
my_model_id=my_model_id,
完成=正确,
)
def hadoopify_函数(self、my_模型、其他_参数):
尝试:
本地(““”hadoop jar/usr/lib/hadoop/hadoop-streaming.jar-D mapred.reduce.tasks=0-文件hadoopify.py-mapper“parse_mapper.py 0 0”-input/user/me/input.csv-output/user/me/output.csv”“)
除SystemExit外,e:
#在这里打印一些关于异常e的有用调试信息!
提升

fabric github页面上对此进行了一些讨论。引发错误的另一个选项是使用设置上下文管理器:

from fabric.api import settings

class Hadoopification(Task):
    ...
    def hadoopify_function(self, my_model, other_args):
        with settings(warn_only=True):
            result = local(...)
        if result.failed:
            # access result.return_code, result.stdout, result.stderr
            raise UsefulException(...)

这样做的好处是允许访问返回代码和结果上的所有其他属性。

冲突是一个有趣的想法。我一次只运行一个芹菜进程,但这并没有解决问题。不过,谢谢你的帮助!我更喜欢这个!现在我只需要写一个有用的异常:)
from fabric.api import settings

class Hadoopification(Task):
    ...
    def hadoopify_function(self, my_model, other_args):
        with settings(warn_only=True):
            result = local(...)
        if result.failed:
            # access result.return_code, result.stdout, result.stderr
            raise UsefulException(...)