コードのコントリビューターガイド—Pythonドキュメント

提供:Dev Guides
Celery/docs/latest/internals/guide
移動先:案内検索

コードへの貢献者ガイド

哲学

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など)ではこれが優先されます。 セロリの例には、signaturechordinspectpromiseなどがあります。

  • ファクトリ関数とメソッドは 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には基本的に2つの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.worker

    これはワーカーの実装です。

  • celery.backends

    タスク結果のバックエンドはここにあります。

  • celery.apps

    主要なユーザーアプリケーション:ワーカーとビート。 これらのコマンドラインラッパーはcelery.binにあります(以下を参照)

  • celery.bin

    コマンドラインアプリケーション。 setup.pyは、これらのsetuptoolsエントリポイントを作成します。

  • celery.concurrency

    実行プールの実装(prefork、eventlet、gevent、solo、thread)。

  • celery.db

    SQLAlchemyデータベース結果バックエンドのデータベースモデル。 (celery.backends.databaseに移動する必要があります)

  • celery.events

    監視イベントの送信と消費には、cursesモニター、イベントダンパー、およびメモリ内クラスター状態を処理するユーティリティも含まれます。

  • celery.execute.trace

    ワーカーがイーガーモードでタスクを実行およびトレースする方法。

  • celery.security

    セキュリティ関連の機能。現在、暗号ダイジェストを使用するシリアライザー。

  • celery.task

    タスクを作成し、ワーカーを制御するためのシングルモードインターフェイス。

  • t.unit(int配布)

    ユニットテストスイート。

  • celery.utils

    Celeryコードベースで使用されるユーティリティ関数。 その多くは、Pythonバージョン間で互換性があるためにあります。

  • celery.contrib

    他の名前空間に適合しない追加のパブリックコード。


労働者の概要

  • celery.bin.worker: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 (cry)/ USR2 (rdb))*バナーと警告を出力します(例:ピクルス警告)* celery worker --purge引数を処理します

  • app.WorkController -> celery.worker.WorkController

    これは、ブートステップを中心に構築された実際のワーカーです。