设置和使用你的开发环境#
推荐的开发设置#
由于 NumPy 包含用 C 和 Cython 编写的部分,需要在使用前进行编译,请确保你已安装必要的编译器和 Python 开发头文件 - 请参阅 从源代码构建 .从 2.0 版本开始,构建 NumPy 需要符合 C11 和 C++17 标准的编译器.
拥有已编译的代码也意味着从开发源导入 NumPy 需要一些额外的步骤,这将在下面解释.在本章的其余部分,我们假设你已按照 Working with scikit-image source code 中的描述设置了你的 git 存储库.
备注
如果你在从源代码构建 NumPy 或设置本地开发环境时遇到问题,你可以尝试使用 GitHub Codespaces 构建 NumPy.它允许你在浏览器中创建正确的开发环境,从而减少了安装本地开发环境和处理不兼容依赖项的需要.
如果你有良好的互联网连接并且想要一个临时设置,那么在 Codespaces 环境中工作通常会更快.有关如何开始使用 Codespaces 的文档,请参阅 the Codespaces docs .为 numpy/numpy 存储库创建 codespace 时,默认的 2 核机器类型即可;4 核会构建和工作得更快一些(当然代价是你的免费使用时间减半).一旦你的 codespace 启动,你可以运行 conda activate numpy-dev ,你的开发环境就完全设置好了 - 然后你可以按照 NumPy 文档的相关部分构建,测试,开发,编写文档并为 NumPy 做出贡献.
使用虚拟环境#
经常被问到的问题是“如何并行设置NumPy的开发版本和我用来完成工作/研究的已发布版本?”.
实现此目的的一种简单方法是例如,使用 pip 或 conda 将已发布版本安装在 site-packages 中,并在虚拟环境中设置开发版本.
如果你使用 conda,我们建议使用 repo 根目录中的 environment.yml 文件为 numpy 开发创建一个单独的虚拟环境(这将创建环境并一次性安装所有开发依赖项):
$ conda env create -f environment.yml # `mamba` works too for this command
$ conda activate numpy-dev
如果你使用 conda 以外的其他方式安装了 Python,请首先安装 virtualenv (可以选择使用 virtualenvwrapper ),然后创建你的 virtualenv(此处命名为 numpy-dev ),激活它,并使用以下命令安装所有项目依赖项:
$ virtualenv numpy-dev
$ source numpy-dev/bin/activate # activate virtual environment
$ python -m pip install -r requirements/all_requirements.txt
现在,每当你想切换到虚拟环境时,你可以使用命令 source numpy-dev/bin/activate ,并使用 deactivate 从虚拟环境退出并返回到之前的 shell.
从源构建#
参见 从源代码构建 .
测试构建#
在运行测试之前,首先安装测试依赖项:
$ python -m pip install -r requirements/test_requirements.txt
$ python -m pip install asv # only for running benchmarks
要构建 NumPy 的开发版本并运行测试,请使用 spin 实用程序生成交互式 shell,并正确设置 Python 导入路径等.要运行测试,请执行以下操作之一:
$ spin test -v
$ spin test numpy/random # to run the tests in a specific module
$ spin test -v -t numpy/_core/tests/test_nditer.py::test_iter_c_order
这会首先构建 NumPy,因此第一次可能需要几分钟.
您还可以使用 spin bench 进行基准测试. 有关更多命令行选项,请参阅 spin --help .
备注
如果上述命令导致 RuntimeError: Cannot parse version 0+untagged.xxxxx ,请运行 git pull upstream main --tags .
可以通过在单独的 -- 之后传递额外的参数将附加参数转发到 pytest . 例如,要运行一个将 --pdb 标志转发到目标的测试方法,请运行以下命令:
$ spin test -t numpy/tests/test_scripts.py::test_f2py -- --pdb
您还可以通过将 -k 参数传递给 pytest 来使用 match test names using python operators
$ spin test -v -t numpy/_core/tests/test_multiarray.py -- -k "MatMul and not vector"
要运行 “doctests” – 检查文档中的代码示例是否正确 – 使用 check-docs spin 命令. 它依赖于 scipy-docs 包,该包在标准库 doctest 包之上提供了几个附加功能. 安装 scipy-doctest 并运行以下命令之一:
$ spin check-docs -v
$ spin check-docs numpy/linalg
$ spin check-docs -v -- -k 'det and not slogdet'
备注
请记住,在提交更改之前,NumPy 的所有测试都应该通过.
备注
测试套件中的某些测试需要大量内存,如果您的系统内存不足,则会跳过这些测试.
其他构建选项#
有关更多选项,包括选择编译器,设置自定义编译器标志和控制并行性,请参阅 Compiler selection and customizing a build (来自 SciPy 文档.)
运行测试#
除了使用 spin ,还有各种方法可以运行测试. 在解释器内部,可以像这样运行测试:
>>> np.test()
>>> np.test('full') # Also run tests marked as slow
>>> np.test('full', verbose=2) # Additionally print test name/file
An example of a successful test :
``4686 passed, 362 skipped, 9 xfailed, 5 warnings in 213.99 seconds``
或者从命令行以类似的方式:
$ python -c "import numpy as np; np.test()"
也可以使用 pytest numpy 运行测试,但是这样找不到 NumPy 特定的插件,这会导致奇怪的副作用.
运行单个测试文件可能很有用;它比运行整个测试套件或整个模块(例如: np.random.test() )快得多. 这可以通过以下方式完成:
$ python path_to_testfile/test_file.py
这也会接受额外的参数,例如 --pdb ,当测试失败或引发异常时,它会将您带入 Python 调试器.
也支持使用 tox 运行测试. 例如,要构建 NumPy 并使用 Python 3.9 运行测试套件,请使用:
$ tox -e py39
有关更广泛的信息,请参见 测试指南 .
注意:不要在没有 spin 的情况下从你的 numpy git 仓库的根目录运行测试,这会导致奇怪的测试错误.
运行 linting#
可以对新添加的 Python 代码行执行 Lint 检查.
使用 pip 安装所有依赖包:
$ python -m pip install -r requirements/linter_requirements.txt
要在提交新代码之前运行 lint 检查,请运行:
$ python tools/linter.py
要检查当前分支中新添加 Python 代码的所有更改与目标分支的更改,请运行:
$ python tools/linter.py
如果没有错误,脚本退出且不显示任何消息. 如果有错误,请检查错误消息以获取详细信息:
$ python tools/linter.py
./numpy/_core/tests/test_scalarmath.py:34:5: E303 too many blank lines (3)
1 E303 too many blank lines (3)
建议在将提交推送到远程分支之前运行 lint 检查,因为 linter 作为 CI 管道的一部分运行.
有关样式指南的更多详细信息:
重建和清理工作区#
在更改编译后的代码后,可以使用与之前使用的相同的构建命令来重建 NumPy - 只有更改的文件会被重新构建. 进行完整构建(有时是必要的)需要首先清理工作区. 这样做的标准方法是(注意:删除任何未提交的文件!):
$ git clean -xdf
当你想放弃所有更改并回到 repo 中最后一次提交时,使用以下方法之一:
$ git checkout .
$ git reset --hard
调试#
另一个经常被问到的问题是“如何在NumPy中调试C代码?”.首先,确保你的系统上安装了gdb,并带有Python扩展(通常是Linux上的默认配置).你可以查看gdb中运行的Python版本来验证你的设置:
(gdb) python
>import sys
>print(sys.version_info)
>end
sys.version_info(major=3, minor=7, micro=0, releaselevel='final', serial=0)
大多数python构建不包含调试符号,并且在构建时启用了编译器优化.为了获得最佳调试体验,建议使用Python的调试版本,参见 高级调试工具 .
在调试方面,NumPy也需要在调试模式下构建.你需要使用 debug 构建类型并禁用优化,以确保在对象构建期间使用 -O0 标志.请注意,在使用 spin build 命令构建之前,NumPy不应安装在你的环境中.
要在构建过程中生成源代码级别的调试信息,请运行:
$ spin build --clean -- -Dbuildtype=debug -Ddisable-optimization=true
备注
如果你正在使用conda环境,请注意conda会自动设置 CFLAGS 和 CXXFLAGS ,并且默认情况下它们将包含 -O2 标志.你可以安全地使用 unset CFLAGS && unset CXXFLAGS 来避免它们,或者在 spin 命令的开头提供它们: CFLAGS="-O0 -g" CXXFLAGS="-O0 -g" .或者,要更永久地控制这些变量,你可以在 <path-to-conda-envs>/numpy-dev/etc/conda/activate.d 目录中创建一个 env_vars.sh 文件.在此文件中,你可以导出 CFLAGS 和 CXXFLAGS 变量.有关完整说明,请参阅 https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#saving-environment-variables.
接下来,你需要编写一个Python脚本来调用你想要调试的C代码.例如 mytest.py
import numpy as np
x = np.arange(5)
np.empty_like(x)
请注意,你的测试文件需要位于你拥有的NumPy克隆之外.现在,你可以运行:
$ spin gdb /path/to/mytest.py
如果你使用clang工具链:
$ spin lldb /path/to/mytest.py
然后在调试器中:
(gdb) break array_empty_like
(gdb) run
lldb 对应指令:
(lldb) breakpoint set --name array_empty_like
(lldb) run
执行现在将停止在相应的C函数,你可以像往常一样逐步执行它.一些有用的Python特定命令可用.例如,要查看你在Python代码中的位置,请使用 py-list ,要查看python回溯,请使用 py-bt .有关更多详细信息,请参见 DebuggingWithGdb .以下是一些常用的命令:
list:列出指定的函数或行.next:单步执行程序,继续执行子例程调用.step:在信号或断点后,继续调试的程序.print:打印表达式EXP的值.
对Python调试的丰富支持要求将Python随附的 python-gdb.py 脚本安装在gdb可以找到它的路径中.如果你从系统软件包管理器安装了Python版本,则可能不需要手动执行任何操作.但是,如果你从源代码构建了Python,则可能需要在你的主目录中创建一个 .gdbinit 文件,将gdb指向你的Python安装位置.例如,通过 pyenv 安装的python版本需要一个包含以下内容的 .gdbinit 文件:
add-auto-load-safe-path ~/.pyenv
强烈建议使用带有调试支持的Python构建NumPy(在Linux发行版上通常打包为 python-dbg ).
理解代码并开始#
更好地理解代码库的最佳策略是选择你想要更改的内容,然后开始阅读代码以了解其工作原理.如有疑问,可以在邮件列表中提问.即使你的pull request不完美也没关系,社区总是乐于提供帮助.作为一个志愿项目,事情有时会被搁置,如果某些事情在大约两到四个星期内没有得到回应,可以随时ping我们.
所以,大胆地选择一个你觉得 NumPy 中令人恼火或困惑的地方,尝试代码,参与讨论,或者查阅参考文档来尝试修复它.事情会慢慢理顺,很快你就会对整个项目有一个相当好的理解.祝你好运!