Python 教學#
在本教學中,我們將依照快速參考章節以及更詳細的製作您的第一個 PR 的步驟章節中指定的步驟,實際對 Arrow 做出功能貢獻。當您發現此處缺少某些資訊時,請隨時瀏覽這些章節。
功能貢獻將被添加到 PyArrow 中的 compute 模組。但是,如果您正在修正錯誤或新增綁定,也可以按照這些步驟操作。
本教學與製作您的第一個 PR 的步驟不同,因為我們將處理一個特定的案例。本教學並非旨在作為逐步指南。
開始吧!
設定#
讓我們設定 Arrow 儲存庫。我們在此假設 Git 已經安裝。否則,請參閱設定章節。
一旦 Apache Arrow 儲存庫 被 fork 後,我們將克隆它,並將主要儲存庫的連結添加到我們的上游。
$ git clone https://github.com/<your username>/arrow.git
$ cd arrow
$ git remote add upstream https://github.com/apache/arrow
建置 PyArrow#
建置 PyArrow 的腳本會根據您使用的作業系統而有所不同。因此,在本教學中,我們僅參考建置過程的說明。
為新功能建立 GitHub issue#
我們將新增一個新功能,該功能模仿 arrow.compute
模組中現有的 min_max
函數,但使間隔在兩個方向上都擴大 1。請注意,這是一個為本指南目的而捏造的函數。
請參閱 此連結 中的 pc.min_max
範例。
首先,我們需要建立一個 GitHub issue,因為它還不存在。建立 GitHub 帳戶後,我們將導航至 GitHub issue 儀表板,然後點擊 New issue 按鈕。
我們應該確保將自己分配給該 issue,以讓其他人知道我們正在處理它。您可以使用新增註解 take
到已建立的 issue 來完成此操作。
另請參閱
要獲取有關 GitHub issue 的更多資訊,請前往指南的 尋找適合新手的好議題 🔎 部分。
開始在新分支上工作#
在開始新增功能之前,我們應該從更新後的主分支建立一個新分支。
$ git checkout main
$ git fetch upstream
$ git pull --ff-only upstream main
$ git checkout -b ARROW-14977
讓我們研究 Arrow 函式庫,看看 pc.min_max
函數在哪裡定義/與 C++ 連接,並了解我們可以在哪裡實作新功能。

我們可以嘗試在 GitHub Apache Arrow 儲存庫中搜尋函數參考。#

並在 pyarrow
資料夾中搜尋 test_compute.py
檔案。#
從搜尋中我們可以看到,該函數在 python/pyarrow/tests/test_compute.py
檔案中進行測試,這表示該函數定義在 compute.py
檔案中。
檢查 compute.py
檔案後,我們可以看到,連同 _compute.pyx
,C++ 中的函數被封裝到 Python 中。我們將在 compute.py
檔案的末尾定義新功能。
讓我們從 arrow/python
目錄中的 Python 控制台中執行一些程式碼,以了解更多關於 pc.min_max
的資訊。
$ cd python
$ python
Python 3.9.7 (default, Oct 22 2021, 13:24:00)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
我們已從 shell 進入 Python 控制台,我們可以進行一些研究
>>> import pyarrow.compute as pc
>>> data = [4, 5, 6, None, 1]
>>> data
[4, 5, 6, None, 1]
>>> pc.min_max(data)
<pyarrow.StructScalar: [('min', 1), ('max', 6)]>
>>> pc.min_max(data, skip_nulls=False)
<pyarrow.StructScalar: [('min', None), ('max', None)]>
我們將把我們的新功能命名為 pc.tutorial_min_max
。我們希望我們的函數的結果(採用相同的輸入資料)為 [('min-', 0), ('max+', 7)]
。如果我們指定應包含 null 值,則結果應等於 pc.min_max
,即 [('min', None), ('max', None)]
。
讓我們將第一個試驗程式碼添加到 arrow/python/pyarrow/compute.py
中,我們首先測試從 C++ 呼叫 "min_max" 函數
def tutorial_min_max(values, skip_nulls=True):
"""
Add docstrings
Parameters
----------
values : Array
Returns
-------
result : TODO
Examples
--------
>>> import pyarrow.compute as pc
>>> data = [4, 5, 6, None, 1]
>>> pc.tutorial_min_max(data)
<pyarrow.StructScalar: [('min-', 0), ('max+', 7)]>
"""
options = ScalarAggregateOptions(skip_nulls=skip_nulls)
return call_function("min_max", [values], options)
為了查看這是否有效,我們需要再次導入 pyarrow.compute
並嘗試
>>> import pyarrow.compute as pc
>>> data = [4, 5, 6, None, 1]
>>> pc.tutorial_min_max(data)
<pyarrow.StructScalar: [('min', 1), ('max', 6)]>
它正在運作。現在我們必須修正限制以獲得修正後的間隔。為此,我們必須對 pyarrow.StructScalar
進行一些研究。在 test_scalars.py 的 test_struct_duplicate_fields
下,我們可以看到如何建立 StructScalar
的範例。我們可以再次執行 Python 控制台並嘗試自己建立一個。
>>> import pyarrow as pa
>>> ty = pa.struct([
... pa.field('min-', pa.int64()),
... pa.field('max+', pa.int64()),
... ])
>>> pa.scalar([('min-', 3), ('max+', 9)], type=ty)
<pyarrow.StructScalar: [('min-', 3), ('max+', 9)]>
注意
在我們還沒有好的文件的情況下,單元測試可能是尋找程式碼範例的好地方。
憑藉關於 StructScalar
和 pc.min_max
函數的額外選項的新知識,我們可以完成工作。
def tutorial_min_max(values, skip_nulls=True):
"""
Compute the minimum-1 and maximum+1 values of a numeric array.
This is a made-up feature for the tutorial purposes.
Parameters
----------
values : Array
skip_nulls : bool, default True
If True, ignore nulls in the input.
Returns
-------
result : StructScalar of min-1 and max+1
Examples
--------
>>> import pyarrow.compute as pc
>>> data = [4, 5, 6, None, 1]
>>> pc.tutorial_min_max(data)
<pyarrow.StructScalar: [('min-', 0), ('max+', 7)]>
"""
options = ScalarAggregateOptions(skip_nulls=skip_nulls)
min_max = call_function("min_max", [values], options)
if min_max[0].as_py() is not None:
min_t = min_max[0].as_py()-1
max_t = min_max[1].as_py()+1
else:
min_t = min_max[0].as_py()
max_t = min_max[1].as_py()
ty = pa.struct([
pa.field('min-', pa.int64()),
pa.field('max+', pa.int64()),
])
return pa.scalar([('min-', min_t), ('max+', max_t)], type=ty)
新增測試#
現在我們應該將單元測試添加到 python/pyarrow/tests/test_compute.py
並執行 pytest。
def test_tutorial_min_max():
arr = [4, 5, 6, None, 1]
l1 = {'min-': 0, 'max+': 7}
l2 = {'min-': None, 'max+': None}
assert pc.tutorial_min_max(arr).as_py() == l1
assert pc.tutorial_min_max(arr,
skip_nulls=False).as_py() == l2
新增單元測試後,我們可以從 shell 執行 pytest。要執行特定的單元測試,請將測試名稱傳遞給 -k
參數。
$ cd python
$ python -m pytest pyarrow/tests/test_compute.py -k test_tutorial_min_max
======================== test session starts ==========================
platform darwin -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/alenkafrim/repos/arrow/python, configfile: setup.cfg
plugins: hypothesis-6.24.1, lazy-fixture-0.6.3
collected 204 items / 203 deselected / 1 selected
pyarrow/tests/test_compute.py . [100%]
======================== 1 passed, 203 deselected in 0.16s ============
$ python -m pytest pyarrow/tests/test_compute.py
======================== test session starts ===========================
platform darwin -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/alenkafrim/repos/arrow/python, configfile: setup.cfg
plugins: hypothesis-6.24.1, lazy-fixture-0.6.3
collected 204 items
pyarrow/tests/test_compute.py ................................... [ 46%]
................................................. [100%]
========================= 204 passed in 0.49s ==========================
另請參閱
有關測試的更多資訊,請參閱 測試 🧪 章節。
檢查樣式#
最後,我們還需要檢查樣式。在 Arrow 中,我們使用一個名為 Archery 的實用程式來檢查程式碼是否符合 PEP 8 樣式指南。
$ archery lint --python --fix
INFO:archery:Running Python formatter (autopep8)
INFO:archery:Running Python linter (flake8)
/Users/alenkafrim/repos/arrow/python/pyarrow/tests/test_compute.py:2288:80: E501 line too long (88 > 79 characters)
使用 --fix
命令,Archery 將嘗試修正樣式問題,但某些問題(如行長度)無法自動修正。我們應該自行進行必要的更正並再次執行 Archery。
$ archery lint --python --fix
INFO:archery:Running Python formatter (autopep8)
INFO:archery:Running Python linter (flake8)
完成。現在讓我們建立 Pull Request!
建立 Pull Request#
首先,讓我們使用 shell 中的 git status
檢查我們的變更,以查看哪些檔案已變更,並僅提交我們正在處理的檔案。
$ git status
On branch ARROW-14977
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: python/pyarrow/compute.py
modified: python/pyarrow/tests/test_compute.py
no changes added to commit (use "git add" and/or "git commit -a")
並使用 git diff
查看檔案中的變更,以便發現我們可能犯的任何錯誤。
$ git diff
diff --git a/python/pyarrow/compute.py b/python/pyarrow/compute.py
index 9dac606c3..e8fc775d8 100644
--- a/python/pyarrow/compute.py
+++ b/python/pyarrow/compute.py
@@ -774,3 +774,45 @@ def bottom_k_unstable(values, k, sort_keys=None, *, memory_pool=None):
sort_keys = map(lambda key_name: (key_name, "ascending"), sort_keys)
options = SelectKOptions(k, sort_keys)
return call_function("select_k_unstable", [values], options, memory_pool)
+
+
+def tutorial_min_max(values, skip_nulls=True):
+ """
+ Compute the minimum-1 and maximum-1 values of a numeric array.
+
+ This is a made-up feature for the tutorial purposes.
+
+ Parameters
+ ----------
+ values : Array
+ skip_nulls : bool, default True
+ If True, ignore nulls in the input.
+
+ Returns
+ -------
+ result : StructScalar of min-1 and max+1
+
+ Examples
+ --------
+ >>> import pyarrow.compute as pc
+ >>> data = [4, 5, 6, None, 1]
+ >>> pc.tutorial_min_max(data)
+ <pyarrow.StructScalar: [('min-', 0), ('max+', 7)]>
+ """
+
+ options = ScalarAggregateOptions(skip_nulls=skip_nulls)
+ min_max = call_function("min_max", [values], options)
+
...
一切看起來都沒問題。現在我們可以提交 (將我們的變更儲存到分支歷史記錄)
$ git commit -am "Adding a new compute feature for tutorial purposes"
[ARROW-14977 170ef85be] Adding a new compute feature for tutorial purposes
2 files changed, 51 insertions(+)
我們可以使用 git log
檢查提交歷史記錄
$ git log
commit 170ef85beb8ee629be651e3f93bcc4a69e29cfb8 (HEAD -> ARROW-14977)
Author: Alenka Frim <frim.alenka@gmail.com>
Date: Tue Dec 7 13:45:06 2021 +0100
Adding a new compute feature for tutorial purposes
commit 8cebc4948ab5c5792c20a3f463e2043e01c49828 (main)
Author: Sutou Kouhei <kou@clear-code.com>
Date: Sun Dec 5 15:19:46 2021 +0900
ARROW-14981: [CI][Docs] Upload built documents
We can use this in release process instead of building on release
manager's local environment.
Closes #11856 from kou/ci-docs-upload
Authored-by: Sutou Kouhei <kou@clear-code.com>
Signed-off-by: Sutou Kouhei <kou@clear-code.com>
...
如果我們在一段時間前開始了分支,我們可能需要 rebase 到上游主分支,以確保沒有合併衝突
$ git pull upstream main --rebase
現在我們可以將我們的工作推送到 GitHub 上名為 origin
的 fork Arrow 儲存庫。
$ git push origin ARROW-14977
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.19 KiB | 1.19 MiB/s, done.
Total 7 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), completed with 6 local objects.
remote:
remote: Create a pull request for 'ARROW-14977' on GitHub by visiting:
remote: https://github.com/AlenkaF/arrow/pull/new/ARROW-14977
remote:
To https://github.com/AlenkaF/arrow.git
* [new branch] ARROW-14977 -> ARROW-14977
現在我們必須前往 GitHub 上的 Arrow 儲存庫 建立 Pull Request。在 GitHub Arrow 頁面(主要或 fork)上,我們將看到一個黃色通知欄,其中註明我們最近已推送到 ARROW-14977 分支。太好了,現在我們可以透過點擊 Compare & pull request 來建立 Pull Request。

Apache Arrow 儲存庫上的通知欄。#
首先,我們需要將標題更改為 ARROW-14977: [Python] 為指南教學新增一個「虛構」功能,以便與 issue 相符。請注意,已新增標點符號!
額外說明:當建立本教學時,我們一直在使用 Jira issue 追蹤器。由於我們目前正在使用 GitHub issue,因此標題將以 GH-14977: [Python] 為指南教學新增一個「虛構」功能 為前綴.
我們還將新增描述,以使其他人清楚我們嘗試做什麼。
一旦我點擊 Create pull request,我的程式碼就可以作為 Apache Arrow 儲存庫中的 Pull Request 進行審查。

這就是我們的 Pull Request!#
Pull Request 已連接到 issue,並且 CI 正在執行。經過一段時間並獲得審查後,我們可以更正程式碼、評論、解決對話等等。我們建立的 Pull Request 可以在 此處 查看。
另請參閱
有關 Pull Request 工作流程的更多資訊,請參閱 Pull request 的生命週期。