使用的环境
windows10
这篇 的目的是 解决我一些困惑, 在这个问题上面卡了几天了, 算是我踩过的坑
celery 在django中使用比较多在 tornado中使用不多,找不到什么资料,所以记录下来。希望后面学习使用celery的小伙伴绕过这个坑,为了不使文章太长决定再写一篇,讲解使用celery 实现定时任务和 周期性任务, 在后面使用celery中 学会了这个简单的demo就会觉得celery再也不难啦。
在这个环境中使用celery 会出现一些问题,连接redis 有问题 后来通过查阅博客解决 ,安装 eventlet 包然后 在运行服务的时候使用 -P eventlet 就可以啦
最初的使用
用来在tornado 框架下使用 celery 来实现周期性任务, 想过使用Tornado PeriodicCallback Crontab定时任务实现 在celery 问题没有解决之前 确实使用的是PeriodicCallback来解决的 但是这个不是直接的crontable 风格解决的,PeriodicCallback 定时直接 通过时间间隔来实现的,需求是在每周一的凌晨3点钟的时候执行代码。使用奔办法,每隔一个小时 执行下要执行的函数,然后在函数中判断当前时间是不是周一 ,再判断当前时间是不是3点到4点之间。如果不是就不进入到业务逻辑代码。好处是直接使用tornado中的轮询,不需要单独去启动第三方的服务。celery 就需要单独启动,这就需要 supervisor 来监控啦,开机时候启动的功能,并且监控着。
最初使用的时候 并且放弃了几天的原因
当在启动服务的时候发现 老报错,自己的写的模块找不到。开始猜测没有写入到环境变量,但是在tornado中可以直接使用的 ,百思不得解,也不知道怎么加入都环境变量。后来看到一篇博客 是直接吧task 文件放在更目录下,直接执行根目录的文件 就可以啦。这是一个特别需要注意的点。如果不子啊更目录的话就要加入到环境变量,下面会将如何加。
先来疯狂一下,再细细品味里面的知识点
第一段代码(windows10 环境)
注意: 这个如果使用命令行的话可以放在任意目录下面不一定要跟目录下面,直接运行也可以
#tasks.py
from celery import Celery
app = Celery('tasks', backend='redis://localhost:6379/0', broker='redis://localhost:6379/0') #配置好celery的backend和broker
@app.task #普通函数装饰为 celery task
def add(x, y):
return x + y
使用 cmd 命令行
直接到tasks 所在的目录下面
执行命令
celery -A tasks worker --loglevel=info
再cmd 再打开一个窗口 进入到tasks 所在的目录
ipython
In [1]: from tasks import add
In [2]: add.delay(3,3)
Out[2]: <AsyncResult: 89668bd4-8b49-4097-a484-937e79770d30>
In [3]:
再看刚才启动的服务的窗口就报错
Traceback (most recent call last):
File "c:\python36\lib\site-packages\billiard\pool.py", line 358, in workloop
result = (True, prepare_result(fun(*args, **kwargs)))
File "c:\python36\lib\site-packages\celery\app\trace.py", line 525, in _fast_trace_task
tasks, accept, hostname = _loc
ValueError: not enough values to unpack (expected 3, got 0)
解决办法:
先ctrl +c 关闭刚才的接口 然后在刚才的命令后面加入 -P eventlet
就可以
celery -A tasks worker --loglevel=info -P eventlet
启动服务后显示信息
-------------- celery@DESKTOP-J6K7J9H v4.1.0 (latentcall)
---- **** -----
--- * *** * -- Windows-10-10.0.16299-SP0 2018-02-01 19:53:01
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: tasks:0x20c27ff4390
- ** ---------- .> transport: redis://localhost:6379/0
- ** ---------- .> results: redis://localhost:6379/0
- *** --- * --- .> concurrency: 8 (eventlet)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. tasks.add
[2018-02-01 19:53:01,751: INFO/MainProcess] Connected to redis://localhost:6379/0
[2018-02-01 19:53:01,764: INFO/MainProcess] mingle: searching for neighbors
[2018-02-01 19:53:02,804: INFO/MainProcess] mingle: all alone
[2018-02-01 19:53:02,816: INFO/MainProcess] pidbox: Connected to redis://localhost:6379/0.
[2018-02-01 19:53:02,906: INFO/MainProcess] celery@DESKTOP-J6K7J9H ready.
执行后
In [3]: add.delay(3,3)
Out[3]: <AsyncResult: 2b5371a6-abbe-48e2-be26-e980068f50af>
[2018-02-01 19:57:01,394: INFO/MainProcess] Connected to redis://localhost:6379/0
[2018-02-01 19:57:01,425: INFO/MainProcess] mingle: searching for neighbors
[2018-02-01 19:57:02,466: INFO/MainProcess] mingle: all alone
[2018-02-01 19:57:02,548: INFO/MainProcess] celery@DESKTOP-J6K7J9H ready.
[2018-02-01 19:57:02,557: INFO/MainProcess] pidbox: Connected to redis://localhost:6379/0.
[2018-02-01 19:57:10,723: INFO/MainProcess] Received task: tasks.add[2b5371a6-abbe-48e2-be26-e980068f50af]
[2018-02-01 19:57:10,724: WARNING/MainProcess] 6
[2018-02-01 19:57:10,731: INFO/MainProcess] Task tasks.add[2b5371a6-abbe-48e2-be26-e980068f50af] succeeded in 0.0s: 6
这样就是运行成功的
直接在中pycharm 通过系统调用
这样直接可以运行
from celery import Celery
from yang.all_test.day24.ddd import MainHandler
app = Celery('tasks', backend='redis://localhost:6379/0', broker='redis://localhost:6379/0') # 配置好celery的backend和broker
@app.task # 普通函数装饰为 celery task
def add(x, y):
print(x+y)
return x + y
if __name__ == '__main__':
import os
cmd = "celery -A tasks worker --loglevel=info -P eventlet"
os.system(cmd)
注意到一个细节,这里引入了一个模块
from yang.all_test.day24.ddd import MainHandler
没有报错,正常执行 add.delay(9,9) 也能够打印执行,没有报找不到这个yang 模块。但是直接通过cmd命令就会出问题
return imp(module, package=package)
File "c:\python36\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "D:\development\work\yang\all_test\day24\tasks.py", line 3, in <module>
from yang.all_test.day24.ddd import MainHandler
ModuleNotFoundError: No module named 'yang'
这就很奇怪
后来发现在pycharm 中好像加入了环境变量。在Python console 中加入了这样的代码
PyDev console: using IPython 6.2.1
import sys; print('Python %s on %s' % (sys.version, sys.platform))
sys.path.extend(['D:\\development\\work', 'D:/development/work'])
现在对这个猜测进行验证将代码放在 tasks.py 文件中
from celery import Celery
# 加入下面这段代码
import sys;
print('Python %s on %s' % (sys.version, sys.platform))
sys.path.extend(['D:\\development\\work', 'D:/development/work'])
from yang.all_test.day24.ddd import MainHandler
app = Celery('tasks', backend='redis://localhost:6379/0', broker='redis://localhost:6379/0') # 配置好celery的backend和broker
@app.task # 普通函数装饰为 celery task
def add(x, y):
print(x+y)
return x + y
if __name__ == '__main__':
import os
cmd = "celery -A tasks worker --loglevel=info -P eventlet"
os.system(cmd)
直接执行cmd 就不会说找不到这yang 这个模块了
–
sys.path.extend ()的作用
将目录加入到环境变量中,当在命令中一如其他模块的时候在环境变零中是找不到的就不会报错,在这个脚本上面执行的时候动态的将根目录加载到环境变量中