如何编写代码片段#

用户通过示例来学习。因此,无论您是编写文档字符串还是用户指南,都应包含说明相关 API 的示例。您的示例应开箱即用,以便用户能够复制它们并根据自己的需求进行调整。

本页介绍如何编写代码片段,以便在 CI 中进行测试。

注意

本指南中的示例使用 reStructuredText。如果您正在编写 Markdown,请使用 MyST 语法。如需了解更多信息,请阅读 MyST 文档

示例类型#

共有三种类型的示例:doctest 风格代码输出风格字面包含

doctest 风格示例#

doctest 风格示例模仿交互式 Python 会话。

.. doctest::

    >>> def is_even(x):
    ...     return (x % 2) == 0
    >>> is_even(0)
    True
    >>> is_even(1)
    False

它们的渲染效果如下

>>> def is_even(x):
...     return (x % 2) == 0
>>> is_even(0)
True
>>> is_even(1)
False

提示

如果您正在编写文档字符串,请排除 .. doctest:: 以简化您的代码。

Example:
    >>> def is_even(x):
    ...     return (x % 2) == 0
    >>> is_even(0)
    True
    >>> is_even(1)
    False

代码输出风格示例#

代码输出风格示例包含普通的 Python 代码。

.. testcode::

    def is_even(x):
        return (x % 2) == 0

    print(is_even(0))
    print(is_even(1))

.. testoutput::

    True
    False

它们的渲染效果如下

def is_even(x):
    return (x % 2) == 0

print(is_even(0))
print(is_even(1))
True
False

字面包含示例#

字面包含示例显示 Python 模块。

.. literalinclude:: ./doc_code/example_module.py
    :language: python
    :start-after: __is_even_begin__
    :end-before: __is_even_end__
# example_module.py

# fmt: off
# __is_even_begin__
def is_even(x):
    return (x % 2) == 0
# __is_even_end__
# fmt: on

它们的渲染效果如下

def is_even(x):
    return (x % 2) == 0

您应该编写哪种类型的示例?#

关于您应该使用哪种样式,没有硬性规定。选择最能说明您的 API 的样式。

提示

如果您不确定使用哪种样式,请使用代码输出风格

何时使用doctest 风格#

如果您正在编写一个强调对象表示形式的小示例,或者您想打印中间对象,请使用doctest 风格

.. doctest::

    >>> import ray
    >>> ds = ray.data.range(100)
    >>> ds.schema()
    Column  Type
    ------  ----
    id      int64
    >>> ds.take(5)
    [{'id': 0}, {'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}]

何时使用代码输出风格#

如果您正在编写一个较长的示例,或者对象表示形式与您的示例无关,请使用代码输出风格

.. testcode::

    from typing import Dict
    import numpy as np
    import ray

    ds = ray.data.read_csv("s3://anonymous@air-example-data/iris.csv")

    # Compute a "petal area" attribute.
    def transform_batch(batch: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]:
        vec_a = batch["petal length (cm)"]
        vec_b = batch["petal width (cm)"]
        batch["petal area (cm^2)"] = vec_a * vec_b
        return batch

    transformed_ds = ds.map_batches(transform_batch)
    print(transformed_ds.materialize())

.. testoutput::

    MaterializedDataset(
       num_blocks=...,
       num_rows=150,
       schema={
          sepal length (cm): double,
          sepal width (cm): double,
          petal length (cm): double,
          petal width (cm): double,
          target: int64,
          petal area (cm^2): double
       }
    )

何时使用字面包含#

如果您正在编写端到端示例,并且您的示例不包含输出,请使用字面包含

如何处理难以测试的示例#

何时可以不测试示例?#

您无需测试依赖于外部系统(如 Weights and Biases)的示例。

跳过doctest 风格示例#

要跳过doctest 风格示例,请在您的 Python 代码末尾添加 # doctest: +SKIP

.. doctest::

    >>> import ray
    >>> ray.data.read_images("s3://private-bucket")  # doctest: +SKIP

跳过代码输出风格示例#

要跳过代码输出风格示例,请在 testcode 块中添加 :skipif: True

.. testcode::
    :skipif: True

    from ray.air.integrations.wandb import WandbLoggerCallback
    callback = WandbLoggerCallback(
        project="Optimization_Project",
        api_key_file=...,
        log_config=True
    )

如何处理长输出或非确定性输出#

如果您的 Python 代码是非确定性的,或者您的输出过长,您可能需要跳过部分或全部输出。

忽略doctest 风格输出#

要忽略doctest 风格输出的某些部分,请用省略号替换有问题的内容。

>>> import ray
>>> ray.data.read_images("s3://anonymous@ray-example-data/image-datasets/simple")
Dataset(num_rows=..., schema=...)

要完全忽略输出,请编写一个代码输出风格的片段。不要使用 # doctest: +SKIP

忽略代码输出风格输出#

如果您的输出部分过长或非确定性,请用省略号替换有问题的内容。

.. testcode::

    import ray
    ds = ray.data.read_images("s3://anonymous@ray-example-data/image-datasets/simple")
    print(ds)

.. testoutput::

    Dataset(num_rows=..., schema=...)

如果您的输出是非确定性的,并且您想显示一个示例输出,请添加 :options: +MOCK

.. testcode::

    import random
    print(random.random())

.. testoutput::
    :options: +MOCK

    0.969461416250246

如果您的输出难以测试,并且您不想显示示例输出,请排除 testoutput

.. testcode::

    print("This output is hidden and untested")

如何测试带有 GPU 的示例#

要配置 Bazel 以使用 GPU 运行示例,请完成以下步骤

  1. 打开相应的 BUILD 文件。如果您的示例位于 doc/ 文件夹中,请打开 doc/BUILD。如果您的示例位于 python/ 文件夹中,请打开像 python/ray/train/BUILD 这样的文件。

  2. 找到 doctest 规则。它看起来像这样

    doctest(
        files = glob(
            include=["source/**/*.rst"],
        ),
        size = "large",
        tags = ["team:none"]
    )
    
  3. 将包含您的示例的文件添加到排除文件列表中。

    doctest(
        files = glob(
            include=["source/**/*.rst"],
            exclude=["source/data/requires-gpus.rst"]
        ),
        tags = ["team:none"]
    )
    
  4. 如果 doctest 规则尚不存在,请创建一个,并将 gpu 设置为 True

    doctest(
        files = [],
        tags = ["team:none"],
        gpu = True
    )
    
  5. 将包含您的示例的文件添加到 GPU 规则中。

    doctest(
        files = ["source/data/requires-gpus.rst"]
        size = "large",
        tags = ["team:none"],
        gpu = True
    )
    

有关实际示例,请参阅 doc/BUILDpython/ray/train/BUILD

如何本地测试示例#

要本地测试示例,请安装 Ray 的 pytest-sphinx 分支。

pip install git+https://github.com/ray-project/pytest-sphinx

然后,在模块、文档字符串或用户指南上运行 pytest。

pytest --doctest-modules python/ray/data/read_api.py
pytest --doctest-modules python/ray/data/read_api.py::ray.data.read_api.range
pytest --doctest-modules doc/source/data/getting-started.rst