有没有办法使用Python RQ从{_main__提交函数

时间:2018-03-02 22:48:30

标签: python python-rq

this question类似,有没有办法将同一文件中定义的函数提交给python-rq? @GG_Python请我为此创建一个新问题。

用法示例:

# somemodule.py
from redis import Redis
from rq import Queue

def somefunc():
    do_something()

q = Queue(connection=Redis('redis://redis'))
q.enqueue(somefunc)

是的,我知道答案是在someothermodule.py中定义somefunc,然后在上面的代码段from someothermodule import somefunc中定义,但我真的不想这样做。也许我对形式过于强硬,但somefunc确实属于它入队的同一个文件(实际上,somefunc采用了一个docker容器名并生成它)。我真的很喜欢整个事情,而不是有两个模块。

我注意到,通过python-rq源代码挖掘,Queue.enqueue实际上可以取一个字符串而不是实际的模块,所以我希望我可以通过somemodule.somefunc,但没有那么幸运。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

查看the source,rq只是检查您的函数的<div class="parent"> <b-upsell-creative [channelId]="(context.channel | async)?.id | async"> </b-upsell-creative> </div> 属性,这可以轻易改变。问题是,为什么确实rq限制你从__module__入队作业?必须有某些原因,并且:函数的模块必须可由工作人员导入。 __main__不是,因为您的主模块在磁盘上未命名为__main__。参见&#34;工作的注意事项&#34;在this page的底部。

此外,您的脚本中包含顶级(非定义)代码,每次由工作人员导入时都会重新调用,您可能不想这样做,因为它会创建新的当每个工人开始时,无限地排队并填充他们的工作。如果你想在主模块中排队一个函数,你可以而且应该使用__main__.py警卫防止这种递归行为。

如果您想将功能及其排队保留在一个模块中,我的建议是除了功能和/或类定义之外,您不要在其中放置任何顶级代码。任何顶级代码,写为函数(例如命名为if __name__ == "__main__")。然后写一个&#34;虚拟&#34;导入真实模块并开始处理的主模块。

示例:

somemodule.py
main()
mainmodule.py
from redis import Redis
from rq import Queue

def somefunc():
    do_something()

def main():
    q = Queue(connection=Redis('redis://redis'))
    q.enqueue(somefunc)

# if the user tried to execute this module, import the right one for them.
# somemodule is then imported twice, once as __main__ and once as somemodule,
# which will use a little extra memory and time but is mostly harmless
if __name__ == "__main__":
    import mainmodule

您也可以将函数的import somemodule somemodule.main() 属性更改为磁盘上模块的实际名称,以便可以导入它。您甚至可以编写装饰器来自动执行此操作:

__module__

为简单起见,装饰器假设您的模块是在其文件名下可导入的单个文件,并且from sys import modules from from os.path import basename, splitext def enqueueable(func): if func.__module__ == "__main__": func.__module__, _ = splitext(basename(modules["__main__"].__file__)) return func @enqueueable def somefunc(): do_something() if __name__ == "__main__": from redis import Redis from rq import Queue q = Queue(connection=Redis('redis://redis')) q.enqueue(somefunc) 扩展名被剥离。你可以使用主模块的包,事情会变得更复杂......所以不要这样做。