与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
,但没有那么幸运。有什么想法吗?
答案 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.pymain()
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)
扩展名被剥离。你可以使用主模块的包,事情会变得更复杂......所以不要这样做。