

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 搭配 Glue 使用 Python AWS 虛擬環境
<a name="aws-glue-programming-python-virtual-environments"></a>

 從 AWS Glue 5.0 開始，您可以在 Python 虛擬環境 (venv) 中執行 ETL 任務。虛擬環境會從任務執行中移除執行時間相依性解析，確保每次執行都使用相同的套件，並防止上游套件變更所造成的失敗。

 AWS Glue 支援兩種使用虛擬環境的方式：
+ **服務產生的虛擬環境** – 可在 AWS Glue 6.0 和更新版本中使用。您可以新增 `--python-virtual-env-storage-prefix` 參數，而 AWS Glue 會為您建置虛擬環境，並在 Amazon S3 中快取它以供日後任務執行。不需要本機建置。
+ **手動建置的虛擬環境** – 適用於 AWS Glue 5.0 及更新版本。您可以在本機電腦或 CI/CD 管道中建置虛擬環境，將其上傳至 Amazon S3，並使用 `--python-virtual-env` 參數加以參考。

 本主題說明如何將 使用 的任務遷移`--additional-python-modules`至任一方法。如需有關管理 Python 相依性的其他方法的資訊，請參閱 [搭配 Glue 使用 Python AWS 程式庫](aws-glue-programming-python-libraries.md)。

## 與 --additional-python-modules 的主要差異
<a name="python-venv-key-differences"></a>

下表`--additional-python-modules`與手動建置的虛擬環境進行比較。


| 功能 | `--additional-python-modules` | `--python-virtual-env` | 
| --- | --- | --- | 
| 基本容器程式庫 (boto3、pandas、 numpy和其他） | 自動提供 | 不可用。您必須在 venv 中包含所有必要的套件。 | 
| 相依性解析 | 在執行時間發生 | 在機器上的建置時間發生 | 
| 執行時間隔離 | 部分。套件安裝在基礎程式庫的頂端。 | 完整。完全取代 Python 環境。 | 

**重要**  
當您遷移至 時`--python-virtual-env`，您必須在虛擬環境中包含任務所需的每個 Python 套件。這包括先前可從 Glue AWS 基礎容器取得的套件，例如 boto3、 numpy和 pandas。這些套件不再是隱含的。

## 選擇合適方案
<a name="python-venv-choosing-an-approach"></a>

使用下表來決定適合您任務的方法。


| 案例 | 建議方法 | 
| --- | --- | 
| 使用少量 pip 套件的簡單任務，無需建置額外負荷 | 服務產生的 venv （新增 `--python-virtual-env-storage-prefix`)。需要 AWS Glue 6.0 或更新版本。 | 
| 建置 venv 的複雜相依性樹狀目錄、完整重現性或 CI/CD 管道 | 手動建置 venv (`--python-virtual-env`)。需要 AWS Glue 5.0 或更新版本。 | 
| `--additional-python-modules` 以最少的變更從 遷移 | 服務產生的 venv （新增 `--python-virtual-env-storage-prefix`)。需要 AWS Glue 6.0 或更新版本。在 AWS Glue 5.0 和 5.1 上，請改用手動建置的虛擬環境。 | 
| 具有自訂套件的私有PyPI索引 | 任一種方法。服務產生的 venv 需要 AWS Glue 6.0 或更新版本，並使用 。 [--python-modules-installer-option](aws-glue-programming-etl-glue-arguments.md#python-modules-installer-option) | 

## 搭配 Amazon S3 快取使用服務產生的虛擬環境
<a name="python-venv-service-generated"></a>

從 AWS Glue 6.0 開始，您可以使用 `--python-virtual-env-storage-prefix` 參數讓 AWS Glue 建置虛擬環境，並在 Amazon S3 中快取它。此方法結合了 的簡單性`--additional-python-modules`與快取虛擬環境的效能優勢。

### 運作方式
<a name="python-venv-service-generated-how-it-works"></a>

當您提供 時`--python-virtual-env-storage-prefix`， AWS Glue 會執行下列動作：
+ **在第一次執行 （快取遺漏）** 時 – AWS Glue 會使用 建立虛擬環境`--system-site-packages`，這會繼承容器套件，例如 numpy、 和 pyarrow. AWS Gluepandas，然後使用 [--additional-python-modules](aws-glue-programming-etl-glue-arguments.md#additional-python-modules) pip 安裝來自 的套件，將虛擬環境封裝為 `.tar.gz` 檔案，並將其上傳至 Amazon S3 字首以供日後重複使用。
+ **稍後執行時 （快取命中）** – AWS Glue 會從 Amazon S3 下載快取檔案、擷取快取`.tar.gz`檔案，並將 Spark 驅動程式和執行程式設定為使用虛擬環境。不會進行 pip 安裝。

### 與手動建置虛擬環境的差異
<a name="python-venv-service-generated-comparison"></a>

下表將服務產生的虛擬環境與手動建置的方法進行比較。


| 功能 | 服務產生的 venv | 手動建置的 venv | 
| --- | --- | --- | 
| 建立責任 | AWS Glue 會自動建置 venv | 您可以在 中建置 venv Docker | 
| 容器套件 | 透過 繼承 `--system-site-packages` | 您必須明確包含所有套件 | 
| 初次執行延遲 | pip 安裝、封裝和 Amazon S3 上傳的額外時間 | 無，因為 venv 是預先建置的 | 
| 稍後執行延遲 | Amazon S3 下載和擷取的額外時間 | Amazon S3 下載和擷取的額外時間 | 
| 確定性 | 我們建議您鎖定套件版本 | 完全確定，因為版本在建置時已鎖定 | 
| PyPI 存取 | 第一次執行時需要 | 不需要，因為 venv 已離線建置 | 

### 設定服務產生的虛擬環境
<a name="python-venv-service-generated-usage"></a>

`--python-virtual-env-storage-prefix` 參數指定 Amazon S3 位置，其中 AWS Glue 存放其建置的虛擬環境，格式為 `s3://{{path}}/`。 AWS Glue 會在第一次任務執行時在此字首快取虛擬環境，並在稍後執行時重複使用。

若要啟用服務產生的虛擬環境，請將 `--python-virtual-env-storage-prefix` 參數新增至您的任務，並保留現有的 `--additional-python-modules` 參數。

```
"--additional-python-modules": "requests==2.32.3,scikit-learn==1.5.0"
"--python-virtual-env-storage-prefix": "s3://{{amzn-s3-demo-bucket}}/venv-cache/"
```

您也可以使用下列選用參數：
+ `--python-virtual-env-version` – 快取虛擬環境的版本識別符。變更此值使快取失效，並強制 AWS Glue 重建虛擬環境。值是字串，因此您可以使用任何適合您工作流程的版本控制方案，例如遞增數字、日期或組建識別符。預設值為 `0`。
+ [--python-modules-installer-option](aws-glue-programming-etl-glue-arguments.md#python-modules-installer-option) – 將選項傳遞至 pip，例如 `--no-deps`或 `--index-url`。

若要啟用現有任務的快取，請新增儲存字首參數。第一次執行需要更長的時間，因為 AWS Glue 會建置和上傳虛擬環境，但稍後執行會使用快取的虛擬環境，且不執行 pip 解析度。

```
# Before
"--additional-python-modules": "requests==2.32.3"

# After
"--additional-python-modules": "requests==2.32.3"
"--python-virtual-env-storage-prefix": "s3://{{amzn-s3-demo-bucket}}/venv-cache/"
```

### Glue AWS 如何快取虛擬環境
<a name="python-venv-service-generated-caching"></a>

AWS Glue 會依您的任務組態來鎖定快取。組態包含來自 的模組`--additional-python-modules`、 的值`--python-modules-installer-option`、Glue AWS 版本和 的值`--python-virtual-env-version`。

未變更的組態會導致快取命中。如果您變更任何這些值， AWS Glue 會建立新的虛擬環境並建立新的快取項目。

AWS Glue 會將每個快取的虛擬環境存放在儲存字首中的個別金鑰下。使用相同模組和安裝程式選項的任務會共用相同的快取項目。

### 限制
<a name="python-venv-service-generated-limitations"></a>
+ 需要 AWS Glue 6.0 或更新版本。
+ 第一次執行需要存取 PyPI或您的私有索引，才能解析相依性。
+ numpy 和 等容器套件pandas會繼承，但不會以版本鎖定。如果您的任務需要確切版本的容器套件，請`--python-virtual-env`改用 。
+ 快取會依組態輸入索引鍵。變更任何模組或版本都會建立新的快取項目，而舊版項目會保留在 Amazon S3 中，直到您將其移除為止。

## 建置您自己的虛擬環境
<a name="python-venv-migration-procedure"></a>

在 AWS Glue 5.0 和更新版本中，您可以自行建置虛擬環境，並使用 `--python-virtual-env` 參數加以參考。當您需要完整重現性、容器套件的確切版本，或在 CI/CD 管道中執行的建置時，請使用此方法。

### 先決條件
<a name="python-venv-prerequisites"></a>

開始前，請確定您有下列項目：
+ [Docker](https://docs.docker.com/get-docker/) 從安裝在本機機器上的 Docker網站，讓您可以在 AWS 與 Glue 相容的環境中建置虛擬環境
+ 用於上傳封裝虛擬環境的 Amazon S3 儲存貯體
+ 設定的 AWS CLI 具有上傳到 Amazon S3 和更新 AWS Glue 任務參數的許可

如需每個 Glue 版本的 Python AWS 版本和平台相容性詳細資訊，請參閱 [附錄 B： AWS Glue 環境詳細資訊](aws-glue-programming-python-libraries.md#glue-python-libraries-environment-details)。

### 步驟 1：建立您的需求檔案
<a name="python-venv-step-1"></a>

建立兩個定義虛擬環境套件的需求檔案。

1. 從 GitHub 網站上的儲存aws-glue-libs庫下載 `base-requirements.txt` AWS Glue 版本。此檔案列出標準 Glue AWS 容器提供的套件。如需本指南中的相同清單，請參閱 [Python 模組已在 Glue AWS 中提供](aws-glue-programming-python-libraries.md#glue-modules-provided)。
   + AWS GitHub網站 Glue 5.0 – [base-requirements.txt](https://raw.githubusercontent.com/awslabs/aws-glue-libs/glue-5.0/base-requirements.txt) 
   + AWS GitHub網站 Glue 5.1 – [base-requirements.txt](https://raw.githubusercontent.com/awslabs/aws-glue-libs/glue-5.1/base-requirements.txt) 
   + AWS GitHub網站 Glue 6.0 – [base-requirements.txt](https://raw.githubusercontent.com/awslabs/aws-glue-libs/main/base-requirements.txt) 

1. 建立 `additional-requirements.txt`。從現有`--additional-python-modules`參數新增套件，每行一個。例如：

   ```
   cryptography
   requests-oauthlib
   sqlalchemy
   ```

**重要**  
如果您的任務使用 AWS Glue Python 程式庫，例如 `GlueContext`或 `DynamicFrame`，您還必須包含來自 PyPI網站的 [AWSGlueDataplanePython](https://pypi.org/project/AWSGlueDataplanePython/) 套件。使用符合您 Glue AWS 版本的版本，如下表所示。


| AWS Glue 版本 | 套件版本 | 
| --- | --- | 
| 5.0 | `AWSGlueDataplanePython==5.0.0` | 
| 5.1 | `AWSGlueDataplanePython==5.1.0` | 
| 6.0 | `AWSGlueDataplanePython==6.0.0` | 

### 步驟 2：建立Dockerfile
<a name="python-venv-step-2"></a>

建立Dockerfile符合您目標 Glue AWS 版本環境的 。如需平台和 Python 版本的詳細資訊，請參閱 [附錄 B： AWS Glue 環境詳細資訊](aws-glue-programming-python-libraries.md#glue-python-libraries-environment-details)。

AWS Glue 5.0 和 5.1 在 Amazon Linux 2023 上使用 Python 3.11。

```
FROM --platform=linux/amd64 public.ecr.aws/amazonlinux/amazonlinux:2023-minimal

RUN dnf install -y python3.11 zip && \
    dnf clean all

WORKDIR /build
```

AWS Glue 6.0 在 Amazon Linux 2023 上使用 Python 3.13。

```
FROM --platform=linux/amd64 public.ecr.aws/amazonlinux/amazonlinux:2023-minimal

RUN dnf install -y python3.13 zip && \
    dnf clean all

WORKDIR /build
```

### 步驟 3：建置和啟動容器
<a name="python-venv-step-3"></a>

建置Docker映像。然後啟動已掛載需求檔案和任務指令碼的容器。

```
docker build --platform linux/amd64 -t glue-venv-builder .

docker run --platform linux/amd64 \
  -v $(pwd)/base-requirements.txt:/working_dir/base-requirements.txt:ro \
  -v $(pwd)/additional-requirements.txt:/working_dir/additional-requirements.txt:ro \
  -v $(pwd)/my_glue_script/:/working_dir/my_glue_script/:ro \
  -v $(pwd):/output \
  -w /working_dir \
  -it glue-venv-builder bash
```

此命令會掛載您的需求檔案和 Glue AWS 任務指令碼目錄。下列步驟使用指令碼目錄進行匯入分析。

### 步驟 4：建置臨時 venv 並探索必要的套件
<a name="python-venv-step-4"></a>

在容器內，建置可鏡射 AWS Glue 執行時間的暫時 venv。然後使用靜態分析來尋找任務所需的最小套件集。

對於使用 Python 3.11 的 AWS Glue 5.0 和 5.1，請執行下列命令。

```
# Create a temporary venv to reproduce the AWS Glue runtime environment
python3.11 -m venv temp_venv
source temp_venv/bin/activate

python3.11 -m pip install --upgrade pip

# Install base container libraries (mirrors what the AWS Glue container provides)
python3.11 -m pip install -r base-requirements.txt

# Install additional Python modules on top (mirrors how AWS Glue installs them at runtime)
python3.11 -m pip install -r additional-requirements.txt

# Freeze the full resolved environment
pip freeze > full-requirements.txt

# Install analysis tools
python3.11 -m pip install pipreqs pip-tools

# Use pipreqs to discover what the script actually imports
# --mode no-pin outputs package names without versions
pipreqs --mode no-pin --savepath discovered-requirements.txt /working_dir/my_glue_script

# Remove packages provided by the Spark runtime
sed -i '/pyspark/d' discovered-requirements.txt
sed -i '/py4j/d' discovered-requirements.txt

# Remove awsglue - install AWSGlueDataplanePython in Step 5 instead
sed -i '/awsglue/d' discovered-requirements.txt

# Use pip-compile to resolve the full dependency tree of the discovered packages,
# constrained to the versions from the temporary venv
pip-compile discovered-requirements.txt -c full-requirements.txt -o final-requirements.txt

echo "=== Final requirements.txt ==="
cat final-requirements.txt

# Deactivate and discard the temporary venv
deactivate
rm -rf temp_venv
```

對於使用 Python 3.13 的 AWS Glue 6.0，請執行下列命令。

```
# Create a temporary venv to reproduce the AWS Glue runtime environment
python3.13 -m venv temp_venv
source temp_venv/bin/activate

python3.13 -m pip install --upgrade pip

# Install base container libraries (mirrors what the AWS Glue container provides)
python3.13 -m pip install -r base-requirements.txt

# Install additional Python modules on top (mirrors how AWS Glue installs them at runtime)
python3.13 -m pip install -r additional-requirements.txt

# Freeze the full resolved environment
pip freeze > full-requirements.txt

# Install analysis tools
python3.13 -m pip install pipreqs pip-tools

# Use pipreqs to discover what the script actually imports
# --mode no-pin outputs package names without versions
pipreqs --mode no-pin --savepath discovered-requirements.txt /working_dir/my_glue_script

# Remove packages provided by the Spark runtime
sed -i '/pyspark/d' discovered-requirements.txt
sed -i '/py4j/d' discovered-requirements.txt

# Remove awsglue - install AWSGlueDataplanePython in Step 5 instead
sed -i '/awsglue/d' discovered-requirements.txt

# Use pip-compile to resolve the full dependency tree of the discovered packages,
# constrained to the versions from the temporary venv
pip-compile discovered-requirements.txt -c full-requirements.txt -o final-requirements.txt

echo "=== Final requirements.txt ==="
cat final-requirements.txt

# Deactivate and discard the temporary venv
deactivate
rm -rf temp_venv
```

**注意**  
檢閱`final-requirements.txt`以確認其看起來正確。如果您的任務使用動態匯入或條件式匯入， pipreqs可能不會偵測到它們。手動將這些套件新增至 檔案。

### 步驟 5：建置生產 venv
<a name="python-venv-step-5"></a>

僅使用任務所需的套件來建立最終 venv。然後將其封裝為 tarball。

對於使用 Python 3.11 的 AWS Glue 5.0 和 5.1，請執行下列命令。

```
python3.11 -m venv pyspark_venv
source pyspark_venv/bin/activate

python3.11 -m pip install --upgrade pip
python3.11 -m pip install -r final-requirements.txt

# Install the AWS Glue Python library that matches your AWS Glue version (see the version
# table in Step 1). Use 5.0.0 for AWS Glue 5.0, or 5.1.0 for AWS Glue 5.1.
python3.11 -m pip install AWSGlueDataplanePython=={{5.0.0}}

python3.11 -m pip install venv-pack
venv-pack -f -o pyspark_venv.tar.gz

cp pyspark_venv.tar.gz /output/
exit
```

對於使用 Python 3.13 的 AWS Glue 6.0，請執行下列命令。

```
python3.13 -m venv pyspark_venv
source pyspark_venv/bin/activate

python3.13 -m pip install --upgrade pip
python3.13 -m pip install -r final-requirements.txt

# Install the AWS Glue Python library (see version table in Step 1)
python3.13 -m pip install AWSGlueDataplanePython==6.0.0

python3.13 -m pip install venv-pack
venv-pack -f -o pyspark_venv.tar.gz

cp pyspark_venv.tar.gz /output/
exit
```

### 步驟 6：上傳至 Amazon S3
<a name="python-venv-step-6"></a>

將封裝的虛擬環境上傳至 Amazon S3 儲存貯體。

```
aws s3 cp pyspark_venv.tar.gz s3://{{amzn-s3-demo-bucket}}/{{path}}/pyspark_venv.tar.gz
```

### 步驟 7：更新任務參數
<a name="python-venv-step-7"></a>

更新您的 AWS Glue 任務組態以使用 `--python-virtual-env`而非 `--additional-python-modules`。

移除 `--additional-python-modules` 參數，並將 `--python-virtual-env` 參數新增至您上傳的 tarball。

```
# Before
"--additional-python-modules": "cryptography"

# After (remove --additional-python-modules entirely)
"--python-virtual-env": "s3://{{amzn-s3-demo-bucket}}/{{path}}/pyspark_venv.tar.gz"
```

## 使用 Kiro 自動化遷移
<a name="python-venv-kiro-migration"></a>

如果您偏好自動化方法，您可以使用 Kiro 網站上[Kiro](https://kiro.dev)提供的 ，[建置您自己的虛擬環境](#python-venv-migration-procedure)從命令列執行中所述的遷移。透過Kiro技能， 會Kiro分析您的 AWS Glue 任務組態、在 中建置虛擬環境Docker，並產生封裝的 tarball。

### 運作方式
<a name="python-venv-kiro-how-it-works"></a>

當您要求 Kiro AWS 將 Glue 任務從 遷移`--additional-python-modules`至 時`--python-virtual-env`，Kiro 會執行下列動作：

1. 從請求中擷取 AWS Glue 版本`--additional-python-modules`、 的值和任務指令碼。

1. 從 AWS Glue 文件擷取 Glue AWS 版本的基本容器模組清單。

1. 在工作目錄中建立建置成品，包括 `base-requirements.txt`、Dockerfile、 `additional-requirements.txt`和建置指令碼。

1. 為 AWS Glue 相容環境建置Docker映像。

1. 在非互動式容器中執行探索和封裝工作流程。

1. 產生 `pyspark_venv.tar.gz`、提示您輸入 Amazon S3 目的地，並上傳 tarball。

1. 顯示更新的任務參數。

### 範例請求
<a name="python-venv-kiro-example"></a>

提供您的 AWS Glue 版本、其他 Python 模組和任務指令碼。例如：

```
I have a Glue 5.1 job with the following:
--additional-python-modules: ephem, awscli

Glue job script:
import awscli
import ephem

Help me migrate to using --python-virtual-env.
```

### 取得 Kiro 技能
<a name="python-venv-kiro-skill"></a>

`venv-migration` 技能檔案會保存在aws-glue-libs儲存庫中，而不是在本指南中。如需技能檔案和安裝說明，請參閱 GitHub 網站上的 [venv-migration 技能](https://github.com/awslabs/aws-glue-libs/blob/main/.kiro/skills/venv-migration/skill.md)。

### 限制
<a name="python-venv-kiro-limitations"></a>
+ Kiro Docker 需要在命令列環境中可用。
+ 不會自動偵測指令碼來源中看不到的動態匯入和條件式匯入。檢閱產生的`final-requirements.txt`檔案，並手動新增任何遺失的套件。
+ 如果您的任務搭配 使用私有 pip 索引`--index-url`，您必須在 Docker 容器中設定該索引的網路存取權。
+ 建置期間的 Pip 衝突可能需要手動解析。如需詳細資訊，請參閱[疑難排解](#python-venv-troubleshooting)。

## 疑難排解
<a name="python-venv-troubleshooting"></a>

使用下列各節來解決搭配 Glue 使用 Python AWS 虛擬環境時的常見問題。

### 解決 pip 版本衝突
<a name="python-venv-troubleshooting-pip-conflicts"></a>

pip 版本衝突表示兩個套件需要相同相依性的不相容版本。若要尋找並修正衝突，請執行下列動作：

1. 讀取 pip 錯誤輸出。當解析度完全失敗時，輸出會命名每個衝突的需求，以及引入它的套件。

1. 預覽哪些 pip 無需安裝任何項目即可解析。將 `--dry-run --report install-report.json`新增至您的安裝命令，如下列範例所示。

   ```
   pip install -r additional-requirements.txt --dry-run --report install-report.json
   ```

1. 檢查 `install-report.json`。報告會列出 pip 選取的每個套件，顯示無提示降級。

1. 在非關鍵套件上放寬版本接腳，或移除限制條件。

### 解決 ModuleNotFoundError
<a name="python-venv-troubleshooting-module-not-found"></a>

此錯誤表示您的虛擬環境不包含必要的套件。常見原因包括下列項目：
+ 您未包含任務所需的基礎容器程式庫。手動建置的虛擬環境不會繼承來自 Glue AWS 容器的套件。
+ 您的任務使用靜態分析期間pipreqs無法偵測的動態匯入。
+ 您的任務需要PySpark相依於執行器節點。

若要解決此問題，請新增缺少的套件，並重新建置虛擬環境。步驟取決於您的任務使用的方法。
+ **手動建置 venv** – 將套件新增至 `final-requirements.txt`，然後重建虛擬環境並重新上傳。
+ **服務產生的 venv** – 將套件新增至 `--additional-python-modules`。新的模組清單會變更快取金鑰，因此 AWS Glue 會在下次任務執行時建立新的虛擬環境。

### 減少 venv tarball 大小
<a name="python-venv-troubleshooting-large-tarball"></a>

如果您的封裝虛擬環境太大，請使用下列方法縮減其大小：
+ 移除指令碼未匯入的不必要套件，例如測試架構和開發工具。
+ `pip install --no-deps` 用於您想要手動控制傳輸相依性的套件。
+ 僅包含指令碼直接匯入的套件，並讓 pip-compile解析所需的最低傳輸相依性。

### 解決平台相容性錯誤
<a name="python-venv-troubleshooting-platform-errors"></a>

當 venv 中的套件為不同的作業系統或架構建置時，就會發生這些錯誤。若要避免這些錯誤：
+ 一律使用 `--platform linux/amd64`旗標在Docker容器內建置虛擬環境。
+ 確認車輪平台標籤符合您的目標 Glue AWS 版本。例如， AWS Glue 5.0 和 5.1 需要 `manylinux2014_x86_64`或相容的平台標籤。
+ 如果沒有 ，請勿直接在 macOS 或 Windows 上建置虛擬環境Docker。