代码贡献者指南 — Python 文档
代码贡献者指南
哲学
API>RCP 优先规则
- API 比可读性更重要
- 可读性比约定更重要
- *; 约定比性能更重要
- *;* ...除非代码是一个经过验证的热点。
最重要的是最终用户 API。 惯例必须搁置一旁,如果最终结果是更好的 API,则任何痛苦总是可以减轻的。
使用的约定和习语
班级
命名
遵循 PEP 8。
类名必须是 CamelCase。
但不是如果它们是动词,动词应为 lower_case:
# - test case for a class class TestMyClass(Case): # BAD pass class test_MyClass(Case): # GOOD pass # - test case for a function class TestMyFunction(Case): # BAD pass class test_my_function(Case): # GOOD pass # - "action" class (verb) class UpdateTwitterStatus: # BAD pass class update_twitter_status: # GOOD pass
笔记
有时将类掩码作为函数是有意义的,并且在 Python 标准库中有优先级(例如,
contextmanager
)。 Celery 示例包括signature
、chord
、inspect
、promise
等等。工厂函数和方法必须是 CamelCase(不包括动词):
class Celery: def consumer_factory(self): # BAD ... def Consumer(self): # GOOD ...
默认值
类属性用作实例的默认值,因为这意味着它们可以通过实例化或继承来设置。
例子:
class Producer:
active = True
serializer = 'json'
def __init__(self, serializer=None, active=None):
self.serializer = serializer or self.serializer
# must check for None when value can be false-y
self.active = active if active is not None else self.active
子类可以更改默认值:
TaskProducer(Producer):
serializer = 'pickle'
并且可以在实例化时设置该值:
>>> producer = TaskProducer(serializer='msgpack')
例外
由对象方法和属性引发的自定义异常应作为属性提供,并记录在抛出的方法/属性中。
这样用户就不必找出从哪里导入异常,而是使用 help(obj)
并直接从实例访问异常类。
示例:
class Empty(Exception):
pass
class Queue:
Empty = Empty
def get(self):
"""Get the next item from the queue.
:raises Queue.Empty: if there are no more items left.
"""
try:
return self.queue.popleft()
except IndexError:
raise self.Empty()
复合材料
与异常类似,复合类应该可以通过继承和/或实例化来覆盖。 在选择要包含的类时可以使用常识,但通常最好添加一个太多:预测用户需要覆盖的内容是困难的(这使我们免于许多猴子补丁)。
示例:
class Worker:
Consumer = Consumer
def __init__(self, connection, consumer_cls=None):
self.Consumer = consumer_cls or self.Consumer
def do_work(self):
with self.Consumer(self.connection) as consumer:
self.connection.drain_events()
应用程序对比 “单一模式”
最初 Celery 是为 Django 开发的,仅仅是因为这使我们能够快速启动项目,同时还拥有庞大的潜在用户群。
在 Django 中,有一个全局设置对象,因此多个 Django 项目不能在同一个进程空间中共存,这给后来在没有这个限制的框架中使用 Celery 带来了问题。
因此引入了应用程序概念。 使用应用程序时,您使用“celery”对象而不是从 Celery 子模块导入内容,这(不幸的是)也意味着 Celery 本质上有两个 API。
这是在单模式下使用 Celery 的示例:
from celery import task
from celery.task.control import inspect
from .models import CeleryStats
@task
def write_stats_to_db():
stats = inspect().stats(timeout=1)
for node_name, reply in stats:
CeleryStats.objects.update_stat(node_name, stats)
使用 Celery 应用程序对象也是如此:
from .celery import celery
from .models import CeleryStats
@app.task
def write_stats_to_db():
stats = celery.control.inspect().stats(timeout=1)
for node_name, reply in stats:
CeleryStats.objects.update_stat(node_name, stats)
在上面的示例中,实际应用程序实例是从项目中的模块导入的,该模块可能如下所示:
from celery import Celery
app = Celery(broker='amqp://')
模块概述
celery.app
这是 Celery 的核心:所有功能的入口点。
celery.loaders
每个应用程序都必须有一个加载器。 加载器决定如何读取配置; 工人开始时会发生什么; 任务何时开始和结束; 等等。
包括的装载机是:
应用程序
默认情况下,自定义 Celery 应用程序实例使用此加载程序。
默认
“单模式”默认使用这个加载器。
也存在扩展加载器,例如 :pypi:`celery-pylons`。
芹菜工人
这是工作人员的实现。
celery.backends
任务结果后端在这里。
celery.apps
主要用户应用:worker 和 beat。 这些的命令行包装器在 celery.bin 中(见下文)
celery.bin
命令行应用程序。
setup.py
为这些创建 setuptools 入口点。celery.concurrency
执行池实现(prefork、eventlet、gevent、solo、thread)。
芹菜数据库
SQLAlchemy 数据库结果后端的数据库模型。 (应移入
celery.backends.database
)celery.events
发送和使用监控事件,还包括curses 监控器、事件转储器和用于处理内存集群状态的实用程序。
celery.execute.trace
工作人员如何在急切模式下执行和跟踪任务。
celery.security
安全相关功能,目前是使用加密摘要的序列化程序。
celery.task
用于创建任务和控制工作人员的单模式界面。
t.unit(整数分布)
单元测试套件。
celery.utils
Celery 代码库使用的实用函数。 其中大部分是为了跨 Python 版本兼容。
celery.contrib
不适合任何其他名称空间的其他公共代码。
工人概览
celery.bin.worker: 工人
这是工作人员的命令行界面。
- 职责:
设置
--detach
时的守护进程,使用
--uid
/--gid
参数时删除权限安装“并发补丁”(eventlet/gevent 猴子补丁)。
app.worker_main(argv)
调用instantiate('celery.bin.worker:Worker')(app).execute_from_commandline(argv)
app.Worker -> celery.apps.worker:Worker
职责: * 设置日志记录和重定向标准输出 * 安装信号处理程序(TERM/HUP/STOP/USR1(哭)/ USR2 (rdb)) * 打印横幅和警告(例如,pickle 警告) * 处理
celery worker --purge
参数app.WorkController -> celery.worker.WorkController
这是真正的工人,围绕着bootsteps 建立起来。