pythonrq:回调模式

pythonrq:回调模式,python,parallel-processing,python-rq,Python,Parallel Processing,Python Rq,我现在有大量文档要处理,并且正在使用PythonRQ来并行化任务 我想一个管道的工作要做的不同的操作是对每个文件执行。例如:A->B->C表示将文档传递给函数A,在A完成后,继续执行B并最后执行C 然而,pythonrq似乎并没有很好地支持管道 下面是一个简单但有点脏的方法。总之,管道中的每个函数都以嵌套方式调用其下一个函数 例如,对于管道a->B->C 在顶层,一些代码是这样编写的: q.enqueue(A,文档) 其中q是队列实例,在函数A中有如下代码: q.enqueue(B,文档) 在B

我现在有大量文档要处理,并且正在使用PythonRQ来并行化任务

我想一个管道的工作要做的不同的操作是对每个文件执行。例如:
A
->
B
->
C
表示将文档传递给函数
A
,在
A
完成后,继续执行
B
并最后执行
C

然而,pythonrq似乎并没有很好地支持管道

下面是一个简单但有点脏的方法。总之,管道中的每个函数都以嵌套方式调用其下一个函数

例如,对于管道
a
->
B
->
C

在顶层,一些代码是这样编写的:

q.enqueue(A,文档)

其中q是
队列
实例,在函数
A
中有如下代码:

q.enqueue(B,文档)

B
中,有如下内容:

q.enqueue(C,文档)

还有比这更优雅的方式吗?例如,ONE函数中的某些代码:

q.enqueue(A,文档)
q、 排队(B,_doc,after=A)
q、 排队(C,文档,后面=B)

参数是与我的需求最接近的参数,但是,运行类似于:


A_job=q.enqueue(A,_doc)
q、 排队(B,取决于=A作业)

不行。由于
q.enqueue(B,dependens\u=A\u job)
在执行
A\u job=q.enqueue(A,the\u doc)
后立即执行。当B排队时,A的结果可能还没有准备好,因为它需要时间来处理

附言:

如果Python RQ在这方面并不擅长,那么我还可以使用Python中的其他工具来达到同样的目的:

  • 循环并行化
  • 管道处理支持
  • dependens_on参数是最接近我要求的参数,但是, 运行类似于:

    A_job=q.enqueue(A,文档)q.enqueue(B,dependens=A_job)

    不行。当q.enqueue(B,dependens_on=A_作业)立即执行时 在执行了一个_job=q.enqueue(A,该_doc)之后。到B被杀的时候 排队时,来自的结果可能尚未准备好,因为需要时间才能完成 过程

    对于这种情况,q.enqueue(B,dependens_on=A_作业)将在一个_作业完成后运行。如果结果没有准备好,q.enqueue(B,dependens\u on=A\u job)将等待它准备好


    它不支持开箱即用,但使用其他技术是可能的

    在我的例子中,我使用缓存来跟踪链中的前一个作业,因此当我们想要将一个新函数排队(在之后立即运行)时,我们可以在调用enqueue()时正确设置其“depends_on”参数

    注意使用附加参数排队:超时,结果\u ttl,ttl'。因为我在rq上运行长作业,所以使用了这些。您可以在pythonrq文档中引用它们的用法

    我使用了django_rq.enqueue(),它是从

    “取决于”-来自:

    依赖-指定必须完成的另一个作业(或作业id) 在此作业将被排队之前

    当B排队时,A的结果可能还没有准备好,因为它需要时间来处理

    我不确定当你最初发布问题时这是否是真的,但无论如何,现在这不是真的。事实上,
    dependens\u on
    功能正是为您描述的工作流而设计的

    的确,这两个功能会立即连续执行

    A_job = q.enqueue(A, the_doc)
    B_job = q.enqueue(B, depends_on=A_job )
    
    但是在
    A
    完成之前,工作人员不会执行
    B
    。在
    A_作业
    成功执行之前,
    B.status=='deferred'
    。一旦
    A.status==“finished”
    ,则
    B
    将开始运行

    这意味着
    B
    C
    可以访问和操作其依赖关系的结果,如下所示:

    导入时间
    从rq导入队列中,获取当前作业
    从redis导入StrictRedis
    conn=StrictRedis()
    q=队列('高',连接=连接)
    定义A():
    时间。睡眠(100)
    返回“结果A”
    def B():
    时间。睡眠(100)
    当前作业=获取当前作业(conn)
    a\u job\u id=当前的\u job.dependencies[0].id
    a_job_result=q.fetch_job(a_job_id)。result
    断言一个_作业_结果==“结果a”
    返回作业结果+结果B
    def C():
    时间。睡眠(100)
    当前作业=获取当前作业(conn)
    b_作业\u id=当前作业。依赖项[0]。id
    b_job_result=q.fetch_job(b_job_id)。result
    assert b_job_result=='result A result b'
    返回b_作业结果+“结果C”
    
    工作人员最终将打印“结果A结果B结果C”

    此外,如果队列中有许多作业,并且
    B
    在执行之前可能要等待一段时间,则可能需要显著增加
    result\u ttl
    或使用
    result\u ttl=-1使其不确定。否则,在为
    result\u ttl
    设置了多少秒后,A的结果将被清除,在这种情况下
    B
    将无法再访问它并返回所需的结果


    然而,设置
    result\u ttl=-1
    具有重要的内存含义。这意味着您的作业结果将永远不会自动清除,并且内存将按比例增长,直到您从redis手动删除这些结果。

    使用3个队列如何?一个用于作业a,另一个用于作业b,最后一个用于作业c,唯一的问题是当作业a结束时,文档在作业b队列中排队,依此类推…即使
    q.enqueue(b,dependens\u=a\u job)
    作业b将在a结束后处理。重要的不是它什么时候处理而不是排队吗?@Marcel使用3个队列与使用单个队列有何不同?它将如何解决这个问题?你找到答案了吗?在每个作业中添加睡眠的目的是什么?@user24
    A_job = q.enqueue(A, the_doc)
    B_job = q.enqueue(B, depends_on=A_job )