为代码库做出贡献# 目录: 代码标准 预提交 可选依赖项 向后兼容性 类型提示 风格指南 pandas 特定类型 验证类型提示 使用 pandas 测试代码中的类型提示 通过持续集成进行测试 测试驱动开发 编写测试 使用pytest 测试结构 首选pytest习语 测试警告 测试异常 涉及文件的测试 涉及网络连接的测试 例子 使用hypothesis 运行测试套件 运行性能测试套件 记录你的代码 代码标准# 编写好的代码不仅仅取决于你写的内容。这也与你如何写它有关。在持续集成测试期间,将运行多个工具来检查代码是否存在风格错误。生成任何警告都会导致测试失败。因此,良好的风格是向 pandas 提交代码的一个要求。 pandas 中有一些工具可以帮助贡献者在为项目做出贡献之前验证他们的更改 ./ci/code_checks.sh:脚本验证文档测试、文档字符串中的格式以及导入的模块。可以使用参数docstrings、code和doctests (例如)独立运行检查;./ci/code_checks.sh doctests pre-commit,我们将在下一节中详细介绍。 此外,由于很多人使用我们的库,因此我们不要突然更改代码,这可能会破坏大量用户代码,这一点很重要,也就是说,我们需要它像 尽可能向后兼容以避免大规模损坏。 预提交# 此外,持续集成将使用预提交挂钩运行代码格式检查, 例如black,,,等等。这些检查中的任何警告都将导致持续集成失败;因此,在提交代码之前自行运行检查会很有帮助。这可以通过安装(如果您按照设置开发环境中的说明进行操作,那么应该已经发生)然后运行来完成:ruffisortclang-formatpre-commit pre-commit install 来自 pandas 存储库的根目录。现在,每次提交更改时都会运行所有样式检查,而无需手动运行每一项。此外,使用pre-commit还可以让您更轻松地了解我们的代码检查的最新变化。 请注意,如果需要,您可以使用 跳过这些检查。git commit --no-verify 如果您不想将pre-commit其用作工作流程的一部分,您仍然可以使用它通过以下方式之一运行检查: pre-commit run --files <files you have modified> pre-commit run --from-ref=upstream/main --to-ref=HEAD --all-files 无需事先完成。pre-commit install 最后,我们还有一些缓慢的预提交检查,这些检查不会在每次提交时运行,但会在持续集成期间运行。您可以通过以下方式手动触发它们: pre-commit run --hook-stage manual --all-files 笔记 您可能需要定期运行, 来清理不再使用的存储库。pre-commit gc 笔记 如果您的安装有冲突virtualenv,那么您可能会收到错误消息 - 请参阅此处。 此外,由于virtualenv 中的错误,如果您使用 conda,则可能会遇到问题。要解决此问题,您可以降级 virtualenv到版本20.0.33。 笔记 如果您最近从上游分支合并到 main 中,则使用的某些依赖项pre-commit可能已更改。确保 更新您的开发环境。 可选依赖项# 可选依赖项(例如 matplotlib)应使用 private helper 导入 pandas.compat._optional.import_optional_dependency。这可确保在不满足依赖性时提供一致的错误消息。 使用可选依赖项的所有方法都应包含一个测试,断言 ImportError未找到可选依赖项时将引发 。如果该库存在,则应跳过此测试。 所有可选依赖项都应记录在 可选依赖项中,并且应在字典中设置所需的最低版本pandas.compat._optional.VERSIONS。 向后兼容性# 请尽量保持向后兼容性。 pandas 有很多用户,有很多现有代码,所以如果可能的话,不要破坏它。如果您认为需要破坏,请在拉取请求中明确说明原因。另外,更改方法签名时要小心,并在需要时添加弃用警告。另外,将已弃用的 sphinx 指令添加到已弃用的函数或方法中。 如果存在与已弃用的函数具有相同参数的函数,则可以使用pandas.util._decorators.deprecate: from pandas.util._decorators import deprecate deprecate('old_func', 'new_func', '1.1.0') 否则,您需要手动执行: import warnings from pandas.util._exceptions import find_stack_level def old_func(): """Summary of the function. .. deprecated:: 1.1.0 Use new_func instead. """ warnings.warn( 'Use new_func instead.', FutureWarning, stacklevel=find_stack_level(), ) new_func() def new_func(): pass 您还需要 编写一个新测试,断言使用已弃用的参数调用时会发出警告 更新所有 pandas 现有测试和代码以使用新参数 有关更多信息,请参阅测试警告。 键入提示# pandas 强烈鼓励使用PEP 484样式类型提示。新的开发应该包含类型提示,并且也接受注释现有代码的拉取请求! 风格指南# 类型导入应遵循约定。您的代码可能会通过预提交检查自动重写以使用一些现代构造(例如使用内置而不是)。from typing import ...listtyping.List 在某些情况下,代码基类可能会定义隐藏内置函数的类变量。这会导致Mypy 1775中所述的问题。这里的防御解决方案是创建内置函数的明确别名并在没有注释的情况下使用它。例如,如果您遇到类似的定义 class SomeClass1: str = None 注释的适当方法如下 str_type = str class SomeClass2: str: str_type = None 在某些情况下,当您比分析器更了解时,您可能会想使用cast打字模块。当使用自定义推理函数时尤其会发生这种情况。例如 from typing import cast from pandas.core.dtypes.common import is_number def cannot_infer_bad(obj: Union[str, int, float]): if is_number(obj): ... else: # Reasonably only str objects would reach this but... obj = cast(str, obj) # Mypy complains without this! return obj.upper() 这里的限制是,虽然人类可以合理地理解is_number捕获int和float类型,但 mypy 还不能做出相同的推论(请参阅mypy #5206 。虽然上述方法有效,但强烈不鼓励cast使用。在适用的情况下重构代码最好采用静态分析 def cannot_infer_good(obj: Union[str, int, float]): if isinstance(obj, str): return obj.upper() else: ... cast对于自定义类型和推理,这并不总是可能的,因此会出现例外情况,但在走上这样的道路之前应该尽一切努力来避免。 pandas 特定类型# pandas 特有的常用类型将出现在pandas._typing中,您应该在适用的情况下使用这些类型。该模块目前是私有的,但最终应该将其公开给想要针对 pandas 实施类型检查的第三方库。 例如,pandas 中的很多函数都接受参数dtype。这可以表示为字符串 like "object"、 a numpy.dtypelikenp.int64甚至 pandas ExtensionDtypelike pd.CategoricalDtype。不必给用户带来不断注释所有这些选项的负担,只需从 pandas._typing 模块导入和重用即可 from pandas._typing import Dtype def as_type(dtype: Dtype) -> ...: ... 该模块最终将容纳重复使用的概念的类型,如“类路径”、“类数组”、“数字”等……并且还可以保存常见参数的别名,如axis.该模块的开发正在进行中,因此请务必参考源代码以获取最新的可用类型列表。 验证类型提示# pandas 使用mypy和Pyright静态分析代码库和类型提示。进行任何更改后,您可以通过运行来确保类型提示保持一致 pre-commit run --hook-stage manual --all-files mypy pre-commit run --hook-stage manual --all-files pyright pre-commit run --hook-stage manual --all-files pyright_reportGeneralTypeIssues # the following might fail if the installed pandas version does not correspond to your local git version pre-commit run --hook-stage manual --all-files stubtest 在你的Python环境中。 警告 请注意,上述命令将使用当前的 python 环境。如果您的 python 软件包比 pandas CI 安装的软件包旧/新,则上述命令可能会失败。当mypy或numpy版本不匹配时,通常会出现这种情况。请参阅如何设置 python 环境或选择最近成功的工作流程,选择“Docstring 验证、键入和其他手动预提交挂钩”作业,然后单击“设置 Conda”和“环境信息”以查看哪些版本pandas CI 安装。 使用 pandas 测试代码中的类型提示# 警告 Pandas 还不是 py.typed 库(第 561章在本地将 pandas 声明为 py.typed 库的主要目的是测试和改进 pandas 内置类型注释。 在 pandas 成为 py.typed 库之前,可以通过在 pandas 安装文件夹中创建一个名为“py.typed”的空文件来轻松试验 pandas 附带的类型注释: python -c "import pandas; import pathlib; (pathlib.Path(pandas.__path__[0]) / 'py.typed').touch()" py.typed 文件的存在向类型检查器发出信号,表明 pandas 已经是一个 py.typed 库。这使得类型检查器知道 pandas 附带的类型注释。 持续集成测试# 提交拉取请求后,pandas 测试套件将在GitHub Actions持续集成服务上自动运行。但是,如果您希望在提交拉取请求之前在分支上运行测试套件,则需要将持续集成服务挂接到您的 GitHub 存储库。有关GitHub Actions 的说明请参见此处。 当您拥有全“绿色”构建时,将考虑合并拉取请求。如果任何测试失败,您将看到一个红色的“X”,您可以单击查看各个失败的测试。这是绿色建筑的一个例子。 测试驱动开发# pandas 非常重视测试,并强烈鼓励贡献者接受 测试驱动开发(TDD)。这个开发过程“依赖于非常短的开发周期的重复:首先,开发人员编写一个(最初失败的)自动化测试用例,定义所需的改进或新功能,然后生成最少量的代码来通过该测试。”因此,在实际编写任何代码之前,您应该编写测试。通常可以从原始 GitHub 问题中获取测试。然而,考虑额外的用例并编写相应的测试总是值得的。 添加测试是代码推送到 pandas 后最常见的请求之一。因此,值得养成提前编写测试的习惯,这样这永远不会成为问题。 编写测试# 所有测试都应进入tests特定包的子目录。该文件夹包含许多当前的测试示例,我们建议您从这些示例中寻找灵感。 作为一般提示,您可以使用集成开发环境 (IDE) 中的搜索功能或终端中的 git grep 命令来查找调用该方法的测试文件。如果您不确定进行测试的最佳位置,请进行最佳猜测,但请注意,审阅者可能会要求您将测试移至其他位置。 要使用 git grep,您可以在终端中运行以下命令: git grep "function_name(" 这将在存储库中的所有文件中搜索文本function_name(。这是一种在代码库中快速定位函数并确定为其添加测试的最佳位置的有用方法。 理想情况下,应该有一个且只有一个明显的测试驻留位置。在我们达到这个理想之前,这些是测试应该在哪里进行的一些经验法则。 您的测试仅依赖于中的代码pd._libs.tslibs吗?此测试可能属于以下之一: 测试.tslibs 笔记 tests.tslibs不应从外部的任何 pandas 模块导入任何文件pd._libs.tslibs 测试标量 测试.tseries.offsets 您的测试仅依赖于 pd._libs 中的代码吗?此测试可能属于以下之一: 测试库 测试.groupby.test_libgroupby 你的测试是算术还是比较方法?此测试可能属于以下之一: 测试.算术 笔记 这些用于可以共享的测试,以使用夹具测试 DataFrame/Series/Index/ExtensionArray 的行为box_with_array 。 测试.frame.test_arithmetic 测试.series.test_arithmetic 您的测试是否采用归约方法(最小值、最大值、总和、乘积……)?此测试可能属于以下之一: 测试.减少 笔记 这些用于可以共享的测试,以测试 DataFrame/Series/Index/ExtensionArray 的行为。 测试.frame.test_reductions 测试.series.test_reductions 测试.test_nanops 您的测试是针对索引方法吗?这是决定测试所属位置的最困难的情况,因为这些测试有很多,并且其中许多测试不止一种方法(例如两者Series.__getitem__和Series.loc.__getitem__) 该测试是否专门测试 Index 方法(例如Index.get_loc, Index.get_indexer)?此测试可能属于以下之一: 测试.indexes.test_indexing 测试.indexes.fooindex.test_indexing 在该文件中应该有一个特定于方法的测试类,例如 TestGetLoc. 在大多数情况下,这些测试中不需要Series任何对象。DataFrame Series 或 DataFrame 索引方法的测试是否不是 __getitem__or __setitem__,例如xs, where, take, mask, lookup, or insert?此测试可能属于以下之一: 测试.frame.indexing.test_methodname 测试.series.indexing.test_methodname 测试是否针对loc、iloc、at或中的任何一个iat?此测试可能属于以下之一: 测试.indexing.test_loc 测试.indexing.test_iloc 测试.indexing.test_at 测试.indexing.test_iat 在适当的文件中,测试类对应于索引器类型(例如TestLocBooleanMask)或主要用例(例如TestLocSetitemWithExpansion)。 请参阅 D) 部分中有关测试多种索引方法的测试的注释。 测试是Series.__getitem__、Series.__setitem__、 DataFrame.__getitem__、 或DataFrame.__setitem__?此测试可能属于以下之一: 测试.series.test_getitem 测试.series.test_setitem 测试.frame.test_getitem 测试.frame.test_setitem 如果很多情况下这样的测试可能会测试多种类似的方法,例如 import pandas as pd import pandas._testing as tm def test_getitem_listlike_of_ints(): ser = pd.Series(range(5)) result = ser[[3, 4]] expected = pd.Series([2, 3]) tm.assert_series_equal(result, expected) result = ser.loc[[3, 4]] tm.assert_series_equal(result, expected) 在这种情况下,测试位置应基于 正在测试的底层方法。或者在测试错误修复的情况下,实际错误的位置。所以在这个例子中,我们知道 调用Series.__getitem__ ,Series.loc.__getitem__所以这实际上是对 的测试 loc.__getitem__。所以这个测试属于tests.indexing.test_loc. 您的测试是针对 DataFrame 还是 Series 方法? 该方法是绘图方法吗?此测试可能属于以下之一: 测试绘图 该方法是IO方法吗?此测试可能属于以下之一: 测试.io 笔记 这包括to_string但不包括在和__repr__中进行了测试。其他类通常有一个文件。tests.frame.test_reprtests.series.test_reprtest_formats 否则此测试可能属于以下之一: 测试.series.methods.test_mymethod 测试.frame.methods.test_mymethod 笔记 如果可以使用固定装置在 DataFrame/Series 之间共享测试 frame_or_series,则按照惯例,它会放入 tests.frame文件中。 您的测试是针对 Index 方法,而不是依赖于 Series/DataFrame 吗?此测试可能属于以下之一: 测试索引 您的测试是针对pandas提供的ExtensionArray 之一(Categorical、、、、、、、、、、 )吗?此测试可能属于以下之一:DatetimeArrayTimedeltaArrayPeriodArrayIntervalArrayNumpyExtensionArrayFloatArrayBoolArrayStringArray 测试.数组 您的测试是否针对所有ExtensionArray 子类(“EA 接口”)?此测试可能属于以下之一: 测试扩展 使用pytest# 测试结构# pandas 现有的测试结构主要是基于类的,这意味着您通常会发现测试包装在类中。 class TestReallyCoolFeature: def test_cool_feature_aspect(self): pass 我们更喜欢使用pytest框架的更实用的风格,它提供了更丰富的测试框架,有助于测试和开发。因此,我们将编写如下测试函数,而不是编写测试类: def test_really_cool_feature(): pass 首选pytest习语# 命名的功能测试仅接受固定装置或参数的参数。def test_* 使用裸露assert来测试标量和真值测试 分别使用和来比较和结果。tm.assert_series_equal(result, expected)tm.assert_frame_equal(result, expected)SeriesDataFrame 测试多个案例时使用@pytest.mark.parameterize 。 当测试用例预计会失败时,请使用pytest.mark.xfail 。 当测试用例永远不会通过时,请使用pytest.mark.skip 。 当测试用例需要特定标记时使用pytest.param 。 如果多个测试可以共享一个安装对象,请使用@pytest.fixture 。 警告 不要使用pytest.xfail(与 不同pytest.mark.xfail),因为它会立即停止测试并且不检查测试是否会失败。如果这是您想要的行为,请pytest.skip改为使用。 如果已知测试会失败,但并不意味着要捕获其失败的方式,则pytest.mark.xfail通常将此方法用于表现出错误行为或未实现功能的测试。如果失败的测试有不稳定的行为,请使用参数strict=False。这将使 pytest 在测试通过时不会失败。使用strict=False是非常不可取的,请仅将其作为最后的手段。 在测试中优先使用装饰器@pytest.mark.xfail和参数pytest.param 而不是使用,以便在 pytest 的收集阶段正确标记测试。对于涉及多个参数、固定装置或这些的组合的测试,只有在测试阶段才有可能失败。为此,请使用夹具request: def test_xfail(request): mark = pytest.mark.xfail(raises=TypeError, reason="Indicate why here") request.applymarker(mark) xfail 不适用于因无效用户参数而导致失败的测试。对于这些测试,我们需要验证是否引发了正确的异常类型和错误消息,pytest.raises而是使用。 测试警告# 用作tm.assert_produces_warning上下文管理器来检查代码块是否引发警告。 with tm.assert_produces_warning(DeprecationWarning): pd.deprecated_function() 如果警告不应该出现在代码块中,则传递False到上下文管理器。 with tm.assert_produces_warning(False): pd.no_warning_function() 如果您有一个会发出警告的测试,但实际上并没有测试警告本身(比如因为将来它将被删除,或者因为我们正在匹配第 3 方库的行为),则pytest.mark.filterwarnings使用忽略该错误。 @pytest.mark.filterwarnings("ignore:msg:category") def test_thing(self): pass 测试异常# 使用pytest.raises作为上下文管理器,具有特定的异常子类(即从不使用Exception)和 中的异常消息match。 with pytest.raises(ValueError, match="an error"): raise ValueError("an error") 涉及文件的测试# 上下文管理器tm.ensure_clean创建一个用于测试的临时文件,其中包含生成的文件名(或您的文件名,如果提供),退出上下文块时会自动删除该文件。 with tm.ensure_clean('my_file_path') as path: # do something with the path 涉及网络连接的测试# 由于网络连接不稳定且缺乏所连接服务器的所有权,单元测试不应通过互联网访问公共数据集。要模拟此交互,请使用pytest-localserver 插件httpserver中的固定装置 。与合成数据。 @pytest.mark.network @pytest.mark.single_cpu def test_network(httpserver): httpserver.serve_content(content="content") result = pd.read_html(httpserver.url) 例子# 这是文件中一组独立测试的示例,pandas/tests/test_cool_feature.py 它说明了我们喜欢使用的多个功能。请记住将 GitHub 问题号添加为新测试的注释。 import pytest import numpy as np import pandas as pd @pytest.mark.parametrize('dtype', ['int8', 'int16', 'int32', 'int64']) def test_dtypes(dtype): assert str(np.dtype(dtype)) == dtype @pytest.mark.parametrize( 'dtype', ['float32', pytest.param('int16', marks=pytest.mark.skip), pytest.param('int32', marks=pytest.mark.xfail( reason='to show how it works'))]) def test_mark(dtype): assert str(np.dtype(dtype)) == 'float32' @pytest.fixture def series(): return pd.Series([1, 2, 3]) @pytest.fixture(params=['int8', 'int16', 'int32', 'int64']) def dtype(request): return request.param def test_series(series, dtype): # GH <issue_number> result = series.astype(dtype) assert result.dtype == dtype expected = pd.Series([1, 2, 3], dtype=dtype) tm.assert_series_equal(result, expected) 测试运行此产量 ((pandas) bash-3.2$ pytest test_cool_feature.py -v =========================== test session starts =========================== platform darwin -- Python 3.6.2, pytest-3.6.0, py-1.4.31, pluggy-0.4.0 collected 11 items tester.py::test_dtypes[int8] PASSED tester.py::test_dtypes[int16] PASSED tester.py::test_dtypes[int32] PASSED tester.py::test_dtypes[int64] PASSED tester.py::test_mark[float32] PASSED tester.py::test_mark[int16] SKIPPED tester.py::test_mark[int32] xfail tester.py::test_series[int8] PASSED tester.py::test_series[int16] PASSED tester.py::test_series[int32] PASSED tester.py::test_series[int64] PASSED 现在可以通过测试名称访问我们拥有的测试parametrized,例如,我们可以运行这些测试来仅子选择那些匹配的测试。-k int8int8 ((pandas) bash-3.2$ pytest test_cool_feature.py -v -k int8 =========================== test session starts =========================== platform darwin -- Python 3.6.2, pytest-3.6.0, py-1.4.31, pluggy-0.4.0 collected 11 items test_cool_feature.py::test_dtypes[int8] PASSED test_cool_feature.py::test_series[int8] PASSED 使用hypothesis# Hypothesis 是一个基于属性的测试库。您可以描述所有有效输入并让假设尝试找到失败的输入,而不是显式参数化测试。更好的是,无论尝试多少个随机示例,假设总是会针对您的断言报告一个最小的反例 - 通常是您从未想过要测试的示例。 有关更多介绍,请参阅假设入门,然后参阅假设文档以了解详细信息。 import json from hypothesis import given, strategies as st any_json_value = st.deferred(lambda: st.one_of( st.none(), st.booleans(), st.floats(allow_nan=False), st.text(), st.lists(any_json_value), st.dictionaries(st.text(), any_json_value) )) @given(value=any_json_value) def test_json_roundtrip(value): result = json.loads(json.dumps(value)) assert value == result 该测试展示了假设的几个有用功能,并展示了一个很好的用例:检查应在大型或复杂的输入域上保持的属性。 为了保持 pandas 测试套件快速运行,如果输入或逻辑简单,则首选参数化测试,而假设测试则保留用于具有复杂逻辑的情况,或者有太多选项组合或微妙的交互需要测试(或想到!)他们全部。 运行测试套件# 然后可以通过键入以下内容直接在 Git 克隆中运行测试(无需安装 pandas): pytest pandas 笔记 如果少数测试未通过,这可能不是您的 pandas 安装的问题。一些测试(例如一些 SQLAlchemy 测试)需要额外的设置,其他测试可能会开始失败,因为非固定库发布了新版本,而其他测试如果并行运行可能会不稳定。只要您可以从本地构建的版本导入 pandas,您的安装就可能没问题,您就可以开始贡献了! 通常,在运行整个套件之前,值得首先围绕您的更改运行一部分测试(提示:您可以使用pandas-coverage 应用程序)来找出哪些测试命中了您修改的代码行,然后仅运行那些)。 最简单的方法是: pytest pandas/path/to/test.py -k regex_matching_test_name 或者使用以下结构之一: pytest pandas/tests/[test-module].py pytest pandas/tests/[test-module].py::[TestClass] pytest pandas/tests/[test-module].py::[TestClass]::[test_method] 使用我们的“pandas-dev”环境中包含的pytest-xdist,可以加快多核计算机上的本地测试速度。然后可以在运行 pytest 时指定数字-n标志,以在指定的核心数量上并行化测试运行,或者自动利用计算机上的所有可用核心。 # Utilize 4 cores pytest -n 4 pandas # Utilizes all available cores pytest -n auto pandas 如果您想进一步加快速度,此命令的更高级用法如下所示 pytest pandas -n 4 -m "not slow and not network and not db and not single_cpu" -r sxX 除了多线程性能提高之外,还通过使用-m标记标志跳过一些测试来提高测试速度: 慢:任何测试都需要很长时间(考虑秒而不是毫秒) 网络:需要网络连接的测试 db:需要数据库的测试(mysql 或 postgres) single_cpu:仅应在单个 cpu 上运行的测试 如果以下选项与您相关,您可能需要启用它: arm_slow:在arm64架构上花费很长时间的任何测试 这些标记在此 toml 文件中定义 ,位于[tool.pytest.ini_options]名为 的列表中markers,以防您想检查是否已创建您感兴趣的新标记。 报告标志-r将显示简短的摘要信息(请参阅pytest 文档)。这里我们显示的数量: s:跳过测试 x:x失败的测试 X:x通过测试 摘要是可选的,如果您不需要添加的信息,可以将其删除。使用并行化选项可以显着减少提交拉取请求之前本地运行测试所需的时间。 如果您需要有关过go发生过的结果的帮助,请在运行命令并打开错误报告之前设置种子,这样我们就可以重现它。这是在 Windows 上设置种子的示例 set PYTHONHASHSEED=314159265 pytest pandas -n 4 -m "not slow and not network and not db and not single_cpu" -r sxX 在 Unix 上使用 export PYTHONHASHSEED=314159265 pytest pandas -n 4 -m "not slow and not network and not db and not single_cpu" -r sxX 有关更多信息,请参阅pytest文档。 此外,还可以运行 pd.test() 使用导入的 pandas 进行类似的测试。 运行性能测试套件# 性能很重要,值得考虑您的代码是否引入了性能回归。 pandas 正在迁移到 asv 基准测试 ,以便轻松监控 pandas 关键操作的性能。这些基准测试都可以在pandas/asv_bench目录中找到,测试结果可以在这里找到。 要使用 asv 的所有功能,您需要conda或 virtualenv。欲了解更多详情,请查看asv 安装网页。 安装asv: pip install git+https://github.com/airspeed-velocity/asv 如果您需要运行基准测试,请将目录更改为asv_bench/并运行: asv continuous -f 1.1 upstream/main HEAD 您可以替换HEAD为您正在处理的分支的名称,并报告变化超过 10% 的基准。该命令conda默认用于创建基准环境。如果你想使用 virtualenv 来代替,请写: asv continuous -f 1.1 -E virtualenv upstream/main HEAD 应将该选项添加到运行基准测试的所有命令中。默认值在 中定义。-E virtualenvasvasv.conf.json 运行完整的基准测试套件可能需要一整天的过程,具体取决于您的硬件及其资源利用率。但是,通常仅将结果的子集粘贴到拉取请求中就足以表明提交的更改不会导致意外的性能下降。您可以使用该-b标志运行特定的基准测试,该标志采用正则表达式。例如,这只会从pandas/asv_bench/benchmarks/groupby.py文件运行基准测试: asv continuous -f 1.1 upstream/main HEAD -b ^groupby 如果您只想从文件运行一组特定的基准测试,则可以使用.分隔符来完成。例如: asv continuous -f 1.1 upstream/main HEAD -b groupby.GroupByMethods 将仅运行GroupByMethods中定义的基准测试groupby.py。 pandas 您还可以使用当前 Python 环境中已安装的版本来运行基准测试套件。如果您没有 virtualenv 或 conda,或者正在使用 上面讨论的方法,这可能很有用;对于就地构建,您需要设置,例如 。您可以通过以下方式使用现有 Python 环境运行基准测试:setup.py developPYTHONPATHPYTHONPATH="$PWD/.." asv [remaining arguments] asv run -e -E existing 或者,要使用特定的 Python 解释器: asv run -e -E existing:python3.6 这将显示基准测试中的 stderr,并使用 python来自$PATH. 有关如何编写基准测试和如何使用 asv 的信息可以在 asv 文档中找到。 记录你的代码# 更改应反映在位于 的发行说明中doc/source/whatsnew/vx.y.z.rst。该文件包含每个版本的持续更改日志。向此文件添加一个条目以记录您的修复、增强或(不可避免的)重大更改。添加条目时,请确保包含 GitHub 问题编号(使用问题/拉取请求编号在:issue:`1234`哪里)。1234您的条目应使用完整的句子和正确的语法来编写。 当提及 API 的某些部分时,请 根据需要使用 Sphinx :func:、:meth:或指令。:class:并非所有公共 API 函数和方法都有文档页面;理想情况下,只有在解决后才会添加链接。您通常可以通过检查以前版本之一的发行说明来找到类似的示例。 如果您的代码是错误修复,请将您的条目添加到相关错误修复部分。避免添加到该Other部分;只有在极少数情况下才应将条目放在那里。错误的描述应尽可能简洁,包括用户可能如何遇到它以及错误本身的指示,例如“产生不正确的结果”或“错误地引发”。可能还需要指出新的行为。 如果您的代码是增强功能,则很可能有必要将使用示例添加到现有文档中。这可以按照有关文档的部分完成。此外,为了让用户知道何时添加此功能,versionadded 使用了该指令。 sphinx 的语法是: .. versionadded:: 2.1.0 无论您在何处放置 sphinx 指令,这都会在 2.1.0 版本中放置文本New。添加新函数或方法( example)或新关键字参数(example)时,也应该将其放入文档字符串中。