AWS Glue와 함께 Python 라이브러리 사용 - AWS Glue

AWS Glue와 함께 Python 라이브러리 사용

AWS Glue ETL과 함께 사용할 추가 Python 모듈 및 라이브러리를 설치할 수 있습니다. AWS Glue 2.0 이상에서 AWS Glue는 Python 패키지 설치 프로그램(pip3)을 사용하여 AWS Glue ETL에서 사용할 추가 모듈을 설치합니다. AWS Glue에서 여러 옵션을 사용하여 추가 Python 모듈을 AWS Glue 작업 환경으로 가져올 수 있습니다. “—additional-python-modules” 파라미터를 사용하여 Python wheel 파일, 요구 사항 파일(requirement.txt, AWS Glue 5.0 이상) 또는 쉼표로 구분된 Python 모듈 목록을 사용하여 모듈을 가져올 수 있습니다.

AWS 공동 책임 모델에 따라 AWS Glue ETL 작업에 사용하는 추가 Python 모듈, 라이브러리 및 해당 종속성을 관리해야 합니다. 여기에는 업데이트 및 보안 패치 적용이 포함됩니다.

AWS Glue에서는 작업 환경의 네이티브 코드 컴파일을 지원하지 않습니다. 하지만 AWS Glue 작업은 Amazon 관리형 Linux 환경 내에서 실행됩니다. Python wheel 파일을 통해 컴파일된 형식으로 네이티브 종속성을 제공할 수 있습니다. AWS Glue 버전 호환성 세부 정보는 위에 있는 표를 참조하세요.

Python 종속성이 컴파일된 네이티브 코드에 전이적으로 종속되는 경우 AWS Glue는 작업 환경에서 네이티브 코드 컴파일을 지원하지 않는다는 제한과 충돌할 수 있습니다. 하지만 AWS Glue 작업은 Amazon 관리형 Linux 환경 내에서 실행됩니다. wheel 배포판을 통해 컴파일된 형식으로 네이티브 종속성을 제공할 수 있습니다. AWS Glue 버전 호환성 세부 정보는 위에 있는 표를 참조하세요.

중요

호환되지 않는 종속성을 사용하는 경우, 특히 대상 환경의 아키텍처 및 시스템 라이브러리와 일치해야 하는 네이티브 확장이 있는 라이브러리에서 런타임 문제가 발생할 수 있습니다. 각 AWS Glue 버전은 라이브러리 및 시스템 구성이 사전 설치된 특정 Python 버전에서 실행됩니다.

pip를 사용하여 AWS Glue 2.0 이상에 추가 Python 모듈 설치

AWS Glue는 Python 패키지 설치 프로그램(pip3)을 사용하여 AWS Glue ETL에서 사용할 추가 모듈을 설치합니다. --additional-python-modules 파라미터를 쉼표로 구분된 Python 모듈 목록과 함께 사용하여 새 모듈을 추가하거나 기존 모듈의 버전을 변경할 수 있습니다. Amazon S3에 배포를 업로드하여 라이브러리의 사용자 지정 배포를 설치한 다음, 모듈 목록에 Amazon S3 객체의 경로를 포함시킬 수 있습니다.

--python-modules-installer-option 파라미터를 사용하여 pip3에 추가 옵션을 전달할 수 있습니다. 예를 들어, "--upgrade"를 전달하여 "--additional-python-modules"로 지정된 패키지를 업그레이드할 수 있습니다. 더 많은 예제를 보려면 Building Python modules from a wheel for Spark ETL workloads using AWS Glue 2.0을 참조하세요.

AWS Glue는 Amazon S3에 저장된 wheel(.whl) 파일을 사용하여 사용자 지정 Python 패키지 설치를 지원합니다. AWS Glue 작업에 wheel 파일을 포함하려면 --additional-python-modules 작업 파라미터에 S3에 저장된 휠 파일 목록(쉼표로 구분)을 제공합니다. 예:

--additional-python-modules s3://amzn-s3-demo-bucket/path/to/package-1.0.0-py3-none-any.whl,s3://your-bucket/path/to/another-package-2.1.0-cp311-cp311-linux_x86_64.whl

이 접근 방식은 사용자 지정 배포판 또는 올바른 운영 체제에 대해 사전 컴파일된 기본 종속성이 있는 패키지가 필요한 경우에도 지원됩니다. 더 많은 예제를 보려면 Building Python modules from a wheel for Spark ETL workloads using AWS Glue 2.0을 참조하세요.

AWS Glue 콘솔의 작업 파라미터 필드를 사용하거나 AWS SDK에서 작업 인수를 변경하여 --additional-python-modules를 지정합니다. 작업 파라미터 설정에 대한 자세한 내용은 AWS Glue 작업에서 작업 파라미터 사용을 참조하세요.

AWS Glue 5.0에서는 Python 라이브러리 종속성을 관리하기 위한 defacto-standard requirements.txt를 제공할 수 있습니다. 이렇게 하려면 다음 두 가지 작업 파라미터를 제공합니다.

  • 키: --python-modules-installer-option

    값: -r

  • 키: --additional-python-modules

    값: s3://path_to_requirements.txt

AWS Glue 5.0 노드는 처음에 requirements.txt에 지정된 python 라이브러리를 로드합니다.

다음은 샘플 requirements.txt입니다.

awswrangler==3.9.1 elasticsearch==8.15.1 PyAthena==3.9.0 PyMySQL==1.1.1 PyYAML==6.0.2 pyodbc==5.2.0 pyorc==0.9.0 redshift-connector==2.1.3 scipy==1.14.1 scikit-learn==1.5.2 SQLAlchemy==2.0.36
중요

작업에 안정적이고 결정적인 AWS Glue 환경이 있는지 확인하려면 requirements.txt에서 고정되지 않은 라이브러리 버전을 사용하지 마세요.

직접 종속성에 wheel을 사용하는 경우 올바르게 고정되지 않으면 호환되지 않는 버전의 전이적 종속성을 가져올 수 있습니다. AWS Glue 작업의 일관성을 위해 모든 라이브러리 버전을 고정하는 것이 좋습니다. AWS Glue에서는 프로덕션 워크로드의 일관성과 신뢰성을 보장하기 위해 Python 환경을 wheel 파일로 패키징하는 것이 권장됩니다.

새 Python 모듈을 업데이트하거나 추가하기 위해 AWS Glue를 사용하면 쉼표로 구분된 Python 모듈 목록을 값으로 사용하여 --additional-python-modules 파라미터를 전달할 수 있습니다. 예를 들어, scikit-learn 모듈을 업데이트/추가하려면 다음 키/값을 사용합니다. "--additional-python-modules", "scikit-learn==0.21.3". 두 가지 옵션으로 Python 모듈을 직접 구성할 수 있습니다.

  • 고정된 Python 모듈(권장)

    "--additional-python-modules", "scikit-learn==0.21.3,ephem==4.1.6"

  • 고정되지 않은 Python 모듈: (프로덕션 워크로드에는 권장되지 않음)

    "--additional-python-modules", "scikit-learn>==0.20.0,ephem>=4.0.0"

    OR

    "--additional-python-modules", "scikit-learn,ephem"

중요

--additional-python-modules에서 직접 Python 모듈을 구성할 때 AWS Glue에서는 AWS Glue 작업 환경의 일관성을 보장하기 위해 고정된 라이브러리 버전 사용이 권장됩니다. 고정되지 않은 라이브러리 버전을 사용하면 최신 버전의 Python 모듈을 가져오지만 이 경우 구분 변경이 발생하거나 Python 모듈이 호환되지 않아 AWS Glue 작업 환경에서 Python 설치에 실패하고 이로 인해 작업이 실패할 수 있습니다. 고객은 프로덕션 워크로드에 고정되지 않은 라이브러리 버전을 사용하지 않는 것이 좋습니다. AWS Glue에서는 프로덕션 워크로드의 일관성과 신뢰성을 보장하기 위해 Python 환경을 wheel 파일로 패키징하는 것이 권장됩니다.

AWS Glue에 추가 Python 라이브러리 설치 모범 사례

(권장) Python 환경을 단일 wheel 파일로 패키징

안전하고 일관적인 환경을 위해 AWS Glue에서는 Python 환경의 스냅샷 생성 및 wheel 파일로의 패키징이 권장됩니다. 이를 통해 참조 Python 모듈 및 전이적 종속성에 대해 Python 환경이 고정됩니다. 이렇게 하면 PyPI와 같은 업스트림 리포지토리와 종속성에서 호환되지 않은 업데이트가 발생할 때 AWS Glue 작업이 영향을 받지 않습니다.

--additional-python-modules 플래그를 사용하여 AWS Glue 작업에 이 파일을 사용할 수 있습니다.

중요

실행 중인 AWS Glue 버전과 유사한 환경에서 다음 스크립트를 실행해야 합니다. Glue 환경 세부 정보 표를 참조하고 동일한 기본 OS 이미지 및 Python 버전을 사용하고 있는지 확인합니다.

#!/bin/bash set -e REQUIREMENTS_FILE="requirements.txt" FINAL_WHEEL_OUTPUT_DIRECTORY="." PACKAGE_NAME=$(basename "$(pwd)") PACKAGE_VERSION="0.1.0" # Help message show_help() { echo "Usage: $0 [options]" echo "" echo "Options:" echo " -r, --requirements FILE Path to requirements.txt file (default: requirements.txt)" echo " -o, --wheel-output DIR Output directory for final wheel (default: current directory)" echo " -n, --name NAME Package name (default: current directory name)" echo " -v, --version VERSION Package version (default: 0.1.0)" echo " -h, --help Show this help message" echo " -g, --glue-version Glue version (required)" echo "" echo "Example:" echo " $0 -r custom-requirements.txt -o dist -n my_package -v 1.2.3 -g 4.0" } # Parse command line arguments while [[ $# -gt 0 ]]; do key="$1" case $key in -r | --requirements) REQUIREMENTS_FILE="$2" shift 2 ;; -o | --wheel-output) FINAL_WHEEL_OUTPUT_DIRECTORY="$2" shift 2 ;; -n | --name) PACKAGE_NAME="$2" shift 2 ;; -v | --version) PACKAGE_VERSION="$2" shift 2 ;; -g | --glue-version) GLUE_VERSION="$2" shift 2 ;; -h | --help) show_help exit 0 ;; *) echo "Unknown option: $1" show_help exit 1 ;; esac done # If package name has dashes, convert to underscores and notify user. We need to check this since we cant import a package with dashes. if [[ "$PACKAGE_NAME" =~ "-" ]]; then echo "Warning: Package name '$PACKAGE_NAME' contains dashes. Converting to underscores." PACKAGE_NAME=$(echo "$PACKAGE_NAME" | tr '-' '_') fi UBER_WHEEL_NAME="${PACKAGE_NAME}-${PACKAGE_VERSION}-py3-none-any.whl" # Check if glue version is provided if [ -z "$GLUE_VERSION" ]; then echo "Error: Glue version is required." exit 1 fi # Validate version format (basic check) if [[ ! "$PACKAGE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && [[ ! "$PACKAGE_VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then echo "Warning: Version '$PACKAGE_VERSION' doesn't follow semantic versioning (x.y.z or x.y)" fi # Check if requirements file exists if [ ! -f "$REQUIREMENTS_FILE" ]; then echo "Error: Requirements file '$REQUIREMENTS_FILE' not found." exit 1 fi # Get relevant platform tags/python versions based on glue version if [[ "$GLUE_VERSION" == "5.0" ]]; then PYTHON_VERSION="3.11" GLIBC_VERSION="2.34" elif [[ "$GLUE_VERSION" == "4.0" ]]; then PYTHON_VERSION="3.10" GLIBC_VERSION="2.26" elif [[ "$GLUE_VERSION" == "3.0" ]]; then PYTHON_VERSION="3.7" GLIBC_VERSION="2.26" elif [[ "$GLUE_VERSION" == "2.0" ]]; then PYTHON_VERSION="3.7" GLIBC_VERSION="2.17" elif [[ "$GLUE_VERSION" == "1.0" ]]; then PYTHON_VERSION="3.6" GLIBC_VERSION="2.17" elif [[ "$GLUE_VERSION" == "0.9" ]]; then PYTHON_VERSION="2.7" GLIBC_VERSION="2.17" else echo "Error: Unsupported glue version '$GLUE_VERSION'." exit 1 fi echo "Using Glue version $GLUE_VERSION" echo "Using Glue python version $PYTHON_VERSION" echo "Using Glue glibc version $GLIBC_VERSION" PIP_PLATFORM_FLAG="" is_glibc_compatible() { # assumes glibc version in the form of major.minor (ex: 2.17) # glue glibc must be >= platform glibc local glue_glibc_version="$GLIBC_VERSION" local platform_glibc_version="$1" # 2.27 (platform) can run on 2.27 (glue) if [[ "$platform_glibc_version" == "$glue_glibc_version" ]]; then return 0 fi local glue_glibc_major="${glue_glibc_version%%.*}" local glue_glibc_minor="${glue_glibc_version#*.}" local platform_glibc_major="${platform_glibc_version%%.*}" local platform_glibc_minor="${platform_glibc_version#*.}" # 3.27 (platform) cannot run on 2.27 (glue) if [[ "$platform_glibc_major" -gt "$glue_glibc_major" ]]; then return 1 fi # 2.34 (platform) cannot run on 2.27 (glue) if [[ "$platform_glibc_major" -eq "$glue_glibc_major" ]] && [[ "$platform_glibc_minor" -gt "$glue_glibc_minor" ]]; then return 1 fi # 2.17 (platform) can run on 2.27 (glue) return 0 } PIP_PLATFORM_FLAG="" if is_glibc_compatible "2.17"; then PIP_PLATFORM_FLAG="${PIP_PLATFORM_FLAG} --platform manylinux2014_x86_64" fi if is_glibc_compatible "2.28"; then PIP_PLATFORM_FLAG="${PIP_PLATFORM_FLAG} --platform manylinux_2_28_x86_64" fi if is_glibc_compatible "2.34"; then PIP_PLATFORM_FLAG="${PIP_PLATFORM_FLAG} --platform manylinux_2_34_x86_64" fi if is_glibc_compatible "2.39"; then PIP_PLATFORM_FLAG="${PIP_PLATFORM_FLAG} --platform manylinux_2_39_x86_64" fi echo "Using pip platform flags: $PIP_PLATFORM_FLAG" # Convert to absolute paths REQUIREMENTS_FILE=$(realpath "$REQUIREMENTS_FILE") FINAL_WHEEL_OUTPUT_DIRECTORY=$(realpath "$FINAL_WHEEL_OUTPUT_DIRECTORY") TEMP_WORKING_DIR=$(mktemp -d) VENV_DIR="${TEMP_WORKING_DIR}/.build_venv" WHEEL_OUTPUT_DIRECTORY="${TEMP_WORKING_DIR}/wheelhouse" # Cleanup function cleanup() { echo "Cleaning up temporary files..." rm -rf "$TEMP_WORKING_DIR" } trap cleanup EXIT echo "=========================================" echo "Building wheel for $PACKAGE_NAME with all dependencies from $REQUIREMENTS_FILE" echo "=========================================" # Determine Python executable to use consistently PYTHON_EXEC=$(which python3 2>/dev/null || which python 2>/dev/null) if [ -z "$PYTHON_EXEC" ]; then echo "Error: No Python executable found" exit 1 fi echo "Using Python: $PYTHON_EXEC" echo "" # Install build requirements echo "Step 1/5: Installing build tools..." echo "----------------------------------------" "$PYTHON_EXEC" -m pip install --upgrade pip build wheel setuptools echo "✓ Build tools installed successfully" echo "" # Create a virtual environment for building echo "Step 2/5: Creating build environment..." echo "----------------------------------------" "$PYTHON_EXEC" -m venv "$VENV_DIR" # Check if virtual environment was created successfully if [ ! -f "$VENV_DIR/bin/activate" ]; then echo "Error: Failed to create virtual environment" exit 1 fi source "$VENV_DIR/bin/activate" # Install pip-tools for dependency resolution "$VENV_DIR/bin/pip" install pip-tools echo "✓ Build environment created successfully" echo "" # Compile requirements to get all transitive dependencies GLUE_PIP_ARGS="$PIP_PLATFORM_FLAG --python-version $PYTHON_VERSION --only-binary=:all:" echo "Step 3/5: Resolving all dependencies..." echo "----------------------------------------" if ! "$VENV_DIR/bin/pip-compile" --pip-args "$GLUE_PIP_ARGS" --no-emit-index-url --output-file "$TEMP_WORKING_DIR/.compiled_requirements.txt" "$REQUIREMENTS_FILE"; then echo "Error: Failed to resolve dependencies. Check for conflicts in $REQUIREMENTS_FILE" exit 1 fi echo "✓ Dependencies resolved successfully" echo "" # Download all wheels for dependencies echo "Step 4/5: Downloading all dependency wheels..." echo "----------------------------------------" "$VENV_DIR/bin/pip" download -r "$TEMP_WORKING_DIR/.compiled_requirements.txt" -d "$WHEEL_OUTPUT_DIRECTORY" $GLUE_PIP_ARGS # Check if any wheels were downloaded if [ ! "$(ls -A "$WHEEL_OUTPUT_DIRECTORY")" ]; then echo "Error: No wheels were downloaded. Check your requirements file." exit 1 fi # Count downloaded wheels (using find instead of ls for better handling) WHEEL_COUNT=$(find "$WHEEL_OUTPUT_DIRECTORY" -name "*.whl" -type f | wc -l | tr -d ' ') echo "✓ Downloaded $WHEEL_COUNT dependency wheels successfully" echo "" # Create a single uber wheel with all dependencies echo "Step 5/5: Creating uber wheel with all dependencies included..." echo "----------------------------------------" # Create a temporary directory for the uber wheel UBER_WHEEL_DIR="$TEMP_WORKING_DIR/uber" mkdir -p "$UBER_WHEEL_DIR" # Create the setup.py file with custom install command cat >"$UBER_WHEEL_DIR/setup.py" <<EOF from setuptools import setup, find_packages import setuptools.command.install import os import glob import subprocess import sys setup( name='${PACKAGE_NAME}', version='${PACKAGE_VERSION}', description='Bundle containing dependencies for ${PACKAGE_NAME}', author='Package Builder', author_email='builder@example.com', packages=['${PACKAGE_NAME}'], # Include the package directory to hold wheels include_package_data=True, package_data={ '${PACKAGE_NAME}': ['wheels/*.whl'], # Include wheels in the package directory } ) EOF # Create a MANIFEST.in file to include all wheels cat >"$UBER_WHEEL_DIR/MANIFEST.in" <<EOF recursive-include ${PACKAGE_NAME}/wheels *.whl EOF # Create an __init__.py file that imports all the bundled wheel files (no auto-install logic) mkdir -p "$UBER_WHEEL_DIR/${PACKAGE_NAME}" cat >"$UBER_WHEEL_DIR/${PACKAGE_NAME}/__init__.py" <<EOF """ ${PACKAGE_NAME} - dependencies can be installed at runtime using the $(load_wheels) function """ from pathlib import Path import logging import subprocess import sys __version__ = "${PACKAGE_VERSION}" def load_wheels(log_level=logging.INFO): logger = logging.getLogger(__name__) handler = logging.StreamHandler(sys.stdout) formatter = logging.Formatter("[Glue Python Wheel Installer] %(asctime)s - %(name)s - %(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(log_level) logger.info("Starting wheel installation process") package_dir = Path(__file__).parent.absolute() wheels_dir = package_dir / "wheels" logger.debug(f"Package directory: {package_dir}") logger.debug(f"Looking for wheels in: {wheels_dir}") if not wheels_dir.exists(): logger.error(f"Wheels directory not found: {wheels_dir}") return False wheel_files = list(wheels_dir.glob("*.whl")) if not wheel_files: logger.warning(f"No wheels found in: {wheels_dir}") return False logger.info(f"Found {len(wheel_files)} wheels") wheel_file_paths = [str(wheel_file) for wheel_file in wheel_files] logger.info(f"Installing {wheel_file_paths}...") try: result = subprocess.run( [sys.executable, "-m", "pip", "install", *wheel_file_paths], check=True, capture_output=True, text=True ) logger.info(f"✓ Successfully installed wheel files") logger.debug(f"pip output: {result.stdout}") except subprocess.CalledProcessError as e: error_msg = f"Failed to install wheel files" logger.error(f"✗ {error_msg}: {e}") if e.stderr: logger.error(f"Error details: {e.stderr}") return False logger.info("All wheels installed successfully") return True EOF cat >"$UBER_WHEEL_DIR/${PACKAGE_NAME}/auto.py" <<EOF """ ${PACKAGE_NAME} - utility module that allows users to automatically install modules by adding $(import ${PACKAGE_NAME}.auto) to the top of their script """ from ${PACKAGE_NAME} import load_wheels load_wheels() EOF # Copy all wheels to the uber wheel directory mkdir -p "$UBER_WHEEL_DIR/${PACKAGE_NAME}/wheels" cp "$WHEEL_OUTPUT_DIRECTORY"/*.whl "$UBER_WHEEL_DIR/${PACKAGE_NAME}/wheels/" # Build the uber wheel echo "Building uber wheel package..." # Install build tools in the current environment "$VENV_DIR/bin/pip" install build if ! (cd "$UBER_WHEEL_DIR" && "$VENV_DIR/bin/python" -m build --skip-dependency-check --wheel --outdir .); then echo "Error: Failed to build uber wheel" exit 1 fi # Ensure output directory exists mkdir -p "$FINAL_WHEEL_OUTPUT_DIRECTORY" # Copy the uber wheel to the output directory FINAL_WHEEL_OUTPUT_PATH="$FINAL_WHEEL_OUTPUT_DIRECTORY/$UBER_WHEEL_NAME" # Find the generated wheel (should be only one in the root directory) GENERATED_WHEEL=$(find "$UBER_WHEEL_DIR" -maxdepth 1 -name "*.whl" -type f | head -1) if [ -z "$GENERATED_WHEEL" ]; then echo "Error: No uber wheel was generated" exit 1 fi cp "$GENERATED_WHEEL" "$FINAL_WHEEL_OUTPUT_PATH" # Get final wheel size for user feedback WHEEL_SIZE=$(du -h "$FINAL_WHEEL_OUTPUT_PATH" | cut -f1) echo "✓ Uber wheel created successfully!" echo "" echo "=========================================" echo "BUILD COMPLETED SUCCESSFULLY!" echo "=========================================" echo "Final wheel: $FINAL_WHEEL_OUTPUT_PATH" echo "Wheel size: $WHEEL_SIZE" echo "Dependencies included: $WHEEL_COUNT packages" echo "" echo "To install the bundle, run:" echo " pip install $FINAL_WHEEL_OUTPUT_PATH" echo "" echo "After installation, you can verify that the bundle works by running:" echo " python -c \"import ${PACKAGE_NAME}; ${PACKAGE_NAME}.load_wheels()\"" echo " or " echo " python -c \"import ${PACKAGE_NAME}.auto\"" echo "========================================="

./wheel_packager.sh -r <path to requirements.txt> -g <glue version> -o <wheel output directory> -n <package name> -v <wheel version>

--additional-python-modules s3://your-bucket/path/to/package_with_dependencies-1.0.0-py3-none-any.whl

# Option 1: automatic installation via import import package_with_dependencies.auto # Option 2: manual installation from package_with_dependencies import load_wheels load_wheels()

PySpark 네이티브 기능으로 Python 파일 포함

AWS Glue는 PySpark를 사용하여 AWS Glue ETL 작업에 Python 파일을 포함합니다. 사용 가능한 경우 종속성을 관리하기 위해 --additional-python-modules를 사용하고 싶을 것입니다. --extra-py-files 작업 파라미터를 사용하여 Python 파일을 포함할 수 있습니다. 종속성은 Amazon S3에서 호스팅되어야 하며, 인수 값은 공백 없이 쉼표로 구분된 Amazon S3 경로 목록이어야 합니다. 이 기능은 Spark에서 사용하는 Python 종속성 관리처럼 작동합니다. Spark의 Python 종속성 관리에 대한 자세한 내용을 알아보려면 Apache Spark 설명서의Using PySpark Native Features(PySpark 기본 기능 사용) 페이지를 참조하세요. --extra-py-files는 추가 코드가 패키징되지 않은 경우 또는 종속성 관리를 위해 기존 도구 체인으로 Spark 프로그램을 마이그레이션하는 경우에 유용합니다. 종속성 도구를 유지 관리하려면 제출하기 전에 종속성을 번들로 묶어야 합니다.

시각적 변환을 사용하는 프로그래밍 스크립트

AWS Glue Studio 시각적 인터페이스를 사용하여 AWS Glue 작업을 생성하면 관리형 데이터 변환 노드와 사용자 지정 시각적 변환을 사용하여 데이터를 변환할 수 있습니다. 관리형 데이터 변환 노드에 대한 자세한 내용은 AWS Glue 관리형 변환으로 데이터 변환 섹션을 참조하세요. 사용자 지정 시각적 변환에 대한 자세한 내용은 사용자 지정 시각적 변환으로 데이터 변환 섹션을 참조하세요. 시각적 변환을 사용하는 스크립트는 작업 언어가 Python 사용으로 설정된 경우에만 생성할 수 있습니다.

시각적 변환을 사용하여 AWS Glue 작업을 생성할 때 AWS Glue Studio는 작업 구성의 --extra-py-files 파라미터를 사용하여 런타임 환경에 이러한 변환을 포함합니다. 작업 파라미터에 대한 자세한 내용을 알아보려면 AWS Glue 작업에서 작업 파라미터 사용 섹션을 참조하세요. 생성된 스크립트 또는 런타임 환경을 변경할 때 스크립트가 성공적으로 실행되도록 하려면 이 작업 구성을 유지해야 합니다.

라이브러리 압축하여 포함

라이브러리가 하나의 .py 파일로 포함되지 않는 한 .zip 아카이브로 패킹되어야 합니다. 패키지 디렉터리는 아가이브의 루트에 있어야 하고 패키지용 __init__.py 파일을 포함해야 합니다. 그러면 Python은 정상적인 방법으로 패키지를 가져올 수 있습니다.

라이브러리가 하나의 .py 파일에 하나의 Python 모듈만 구성할 수 있으면 모듈을 .zip에 넣을 필요가 없습니다.

AWS Glue Studio 노트북에서 Python 라이브러리 로드

AWS Glue Studio 노트북에서 Python 라이브러리를 지정하려면 추가 Python 모듈 설치를 참조하세요.

AWS Glue 0.9/1.0의 개발 엔드포인트에서 Python 라이브러리 로딩

다른 ETL 스크립트를 설치하기 위해 다른 라이브러리를 사용할 경우, 각 세트에 따라 개별 개발 엔드포인트를 설치하거나 개발 엔드포인트가 스크립트를 스위치할 때마다 로딩되는 라이브러리 .zip 파일(들)을 덮어쓰기할 수 있습니다.

콘솔을 사용하여 개발 엔드포인트를 생성할 때 개발 엔드포인트를 위한 하나 이상의 .zip 파일을 지정할 수 있습니다. 이름과 IAM 역할을 할당한 후 [스크립트 라이브러리 및 작업 파라미터(선택 사항)(Script Libraries and job parameters (optional))]를 선택하고 [Python 라이브러리 경로(Python library path)] 상자에 라이브러리 .zip 파일에 대한 전체 Amazon S3 경로를 입력합니다. 예:

s3://bucket/prefix/site-packages.zip

원한다면, 다음과 같이 빈 칸없이 쉼표로만 나뉜 파일까지의 전체 경로를 지정할 수 있습니다.

s3://bucket/prefix/lib_A.zip,s3://bucket_B/prefix/lib_X.zip

이런 .zip 파일을 나중에 업데이트하면 콘솔을 사용하여 개발 엔드포인트로 이러 파일을 다시 가져올 수 있습니다. 해당 개발자 엔드포인트로 이동하여 옆에 있는 확인란을 선택한 다음 [작업(Action)] 메뉴에서 [ETL 라이브러리 업데이트(Update ETL libraries)]를 선택합니다.

비슷한 방식으로 AWS Glue API를 사용하여 라이브러리 파일을 지정할 수 있습니다. CreateDevEndpoint 작업(Python: create_dev_endpoint)를 호출하여 개발 엔드포인트를 생성하고자 할 때 다음과 같은 호출에 따라 ExtraPythonLibsS3Path 파라미터의 라이브러리까지 하나 이상의 전체 경로를 지정할 수 있습니다.

dep = glue.create_dev_endpoint( EndpointName="testDevEndpoint", RoleArn="arn:aws:iam::123456789012", SecurityGroupIds="sg-7f5ad1ff", SubnetId="subnet-c12fdba4", PublicKey="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtp04H/y...", NumberOfNodes=3, ExtraPythonLibsS3Path="s3://bucket/prefix/lib_A.zip,s3://bucket_B/prefix/lib_X.zip")

개발 엔드포인트를 업데이트할 때 DevEndpointCustomLibraries 객체를 사용하고 UpdateDevEndpoint(update_dev_endpoint)를 호출할 때 UpdateEtlLibraries 파라미터를 True로 설정하여 로드하는 라이브러리를 업데이트할 수도 있습니다.

Job 혹은 JobRun에서 Python 라이브러리 사용

콘솔에서 새로운 작업을 생성하고자 할 경우, [스크립트 라이브러리 및 작업 파라미터(선택 사항)(Script Libraries and job parameters (optional))]를 선택하고 개발 엔드포인트를 생성할 때와 동일한 방식으로 전체 Amazon S3 라이브러리 경로를 입력하여 라이브러리 .zip 파일을 하나 이상 지정할 수 있습니다.

s3://bucket/prefix/lib_A.zip,s3://bucket_B/prefix/lib_X.zip

CreateJob(create_job)를 호출한다면 다음과 같은 --extra-py-files 기본 파라미터를 사용하여 기본 라이브러리까지 하나 이상의 전체 경로를 지정할 수 있습니다.

job = glue.create_job(Name='sampleJob', Role='Glue_DefaultRole', Command={'Name': 'glueetl', 'ScriptLocation': 's3://my_script_bucket/scripts/my_etl_script.py'}, DefaultArguments={'--extra-py-files': 's3://bucket/prefix/lib_A.zip,s3://bucket_B/prefix/lib_X.zip'})

그런 다음 JobRun을 시작할 경우, 다른 것으로 기본 라이브러리 설정을 재정의할 수 있습니다.

runId = glue.start_job_run(JobName='sampleJob', Arguments={'--extra-py-files': 's3://bucket/prefix/lib_B.zip'})

Python 종속성 사전 분석

AWS Glue에 배포하기 전에 잠재적 종속성 문제를 사전에 식별하기 위해 종속성 분석 도구를 사용하여 대상 AWS Glue 환경에 맞춰 Python 패키지를 검증할 수 있습니다.

AWS에서는 AWS Glue 환경에 특별히 설계된 오픈 소스 Python 종속성 분석기 도구를 제공합니다. 이 도구는 AWS Glue 샘플 리포지토리에서 사용할 수 있고 배포 전에 로컬에서 종속성을 검증하는 데 사용할 수 있습니다.

이 분석을 통해 종속성에서 일관적인 프로덕션 배포를 위해 모든 라이브러리 버전을 고정시키는 권장 관행을 따를 수 있습니다. 자세한 내용은 도구의 README를 참조하세요.

AWS Glue Python Dependency Analyzer는 대상 AWS Glue 환경과 일치하는 플랫폼별 제약 조건으로 pip 설치를 시뮬레이션하여 고정되지 않은 종속성과 버전 충돌을 식별하는 데 도움이 됩니다.

# Analyze a single Glue job python glue_dependency_analyzer.py -j my-glue-job # Analyze multiple jobs with specific AWS configuration python glue_dependency_analyzer.py -j job1 -j job2 --aws-profile production --aws-region us-west-2

도구는 다음과 같은 경우에 플래그를 지정합니다.

  • 작업 실행 간에 다른 버전이 설치될 수 있는 고정되지 않은 종속성

  • 패키지 간 버전 충돌

  • 대상 AWS Glue 환경에 종속성을 사용할 수 없음

Amazon Q Developer는 AWS 애플리케이션을 이해하고, 구축하고, 확장하고, 운영하는 데 도움을 줄 수 있는 생성형 인공 지능(AI) 기반 대화형 어시스턴트입니다. Amazon Q 시작 안내서의 지침에 따라 다운로드할 수 있습니다.

Amazon Q Developer를 사용하여 Python 종속성으로 인한 작업 실패를 분석 및 수정할 수 있습니다. 작업 <Job-Name> 자리표시자를 Glue 작업 이름으로 바꾸어 다음 프롬프트를 사용하는 것이 좋습니다.

I have an AWS Glue job named <Job-Name> that has failed due to Python module installation conflicts. Please assist in diagnosing and resolving this issue using the following systematic approach. Proceed once sufficient information is available. Objective: Implement a fix that addresses the root cause module while minimizing disruption to the existing working environment. Step 1: Root Cause Analysis • Retrieve the most recent failed job run ID for the specified Glue job • Extract error logs from CloudWatch Logs using the job run ID as a log stream prefix • Analyze the logs to identify: • The recently added or modified Python module that triggered the dependency conflict • The specific dependency chain causing the installation failure • Version compatibility conflicts between required and existing modules Step 2: Baseline Configuration Identification • Locate the last successful job run ID prior to the dependency failure • Document the Python module versions that were functioning correctly in that baseline run • Establish the compatible version constraints for conflicting dependencies Step 3: Targeted Resolution Implementation • Apply pinning by updating the job's additional_python_modules parameter • Pin only the root cause module and its directly conflicting dependencies to compatible versions, and do not remove python modules unless necessary • Preserve flexibility for non-conflicting modules by avoiding unnecessary version constraints • Deploy the configuration changes with minimal changes to the existing configuration and execute a validation test run. Do not change the Glue versions. Implementation Example: Scenario: Recently added pandas==2.0.0 to additional_python_modules Error: numpy version conflict (pandas 2.0.0 requires numpy>=1.21, but existing job code requires numpy<1.20) Resolution: Update additional_python_modules to "pandas==1.5.3,numpy==1.19.5" Rationale: Use pandas 1.5.3 (compatible with numpy 1.19.5) and pin numpy to last known working version Expected Outcome: Restore job functionality with minimal configuration changes while maintaining system stability.

프롬프트를 통해 Q에 다음을 지시합니다.

  1. 최근에 실패한 작업 실행 ID 가져오기

  2. 관련 로그 및 세부 정보 찾기

  3. 성공적인 작업 실행을 찾아 변경된 Python 패키지 감지

  4. 구성 수정 및 다른 테스트 실행 트리거

AWS Glue에서 이미 제공되는 Python 모듈

이러한 제공된 모듈의 버전을 변경하려면 새 버전에 --additional-python-modules 작업 파라미터를 제공합니다.

AWS Glue version 5.0

AWS Glue 버전 5.0은 기본적으로 다음과 같은 Python 모듈을 포함합니다.

  • aiobotocore==2.13.1

  • aiohappyeyeballs==2.3.5

  • aiohttp==3.10.1

  • aioitertools==0.11.0

  • aiosignal==1.3.1

  • appdirs==1.4.4

  • attrs==24.2.0

  • boto3==1.34.131

  • botocore==1.34.131

  • certifi==2024.7.4

  • charset-normalizer==3.3.2

  • contourpy==1.2.1

  • cycler==0.12.1

  • fonttools==4.53.1

  • frozenlist==1.4.1

  • fsspec==2024.6.1

  • idna==2.10

  • jmespath==0.10.0

  • kaleido==0.2.1

  • kiwisolver==1.4.5

  • matplotlib==3.9.0

  • multidict==6.0.5

  • numpy==1.26.4

  • packaging==24.1

  • pandas==2.2.2

  • pillow==10.4.0

  • pip==23.0.1

  • plotly==5.23.0

  • pyarrow==17.0.0

  • pyparsing==3.1.2

  • python-dateutil==2.9.0.post0

  • pytz==2024.1

  • requests==2.32.2

  • s3fs==2024.6.1

  • s3transfer==0.10.2

  • seaborn==0.13.2

  • setuptools==59.6.0

  • six==1.16.0

  • tenacity==9.0.0

  • tzdata==2024.1

  • urllib3==1.25.10

  • virtualenv==20.4.0

  • wrapt==1.16.0

  • yarl==1.9.4

AWS Glue version 4.0

AWS Glue 버전 4.0은 기본적으로 다음과 같은 Python 모듈을 포함합니다.

  • aiobotocore==2.4.1

  • aiohttp==3.8.3

  • aioitertools==0.11.0

  • aiosignal==1.3.1

  • async-timeout==4.0.2

  • asynctest==0.13.0

  • attrs==22.2.0

  • avro-python3==1.10.2

  • boto3==1.24.70

  • botocore==1.27.59

  • certifi==2021.5.30

  • chardet==3.0.4

  • charset-normalizer==2.1.1

  • click==8.1.3

  • cycler==0.10.0

  • Cython==0.29.32

  • fsspec==2021.8.1

  • idna==2.10

  • importlib-metadata==5.0.0

  • jmespath==0.10.0

  • joblib==1.0.1

  • kaleido==0.2.1

  • kiwisolver==1.4.4

  • matplotlib==3.4.3

  • mpmath==1.2.1

  • multidict==6.0.4

  • nltk==3.7

  • numpy==1.23.5

  • packaging==23.0

  • pandas==1.5.1

  • patsy==0.5.1

  • Pillow==9.4.0

  • pip==23.0.1

  • plotly==5.16.0

  • pmdarima==2.0.1

  • ptvsd==4.3.2

  • pyarrow==10.0.0

  • pydevd==2.5.0

  • pyhocon==0.3.58

  • PyMySQL==1.0.2

  • pyparsing==2.4.7

  • python-dateutil==2.8.2

  • pytz==2021.1

  • PyYAML==6.0.1

  • regex==2022.10.31

  • requests==2.23.0

  • s3fs==2022.11.0

  • s3transfer==0.6.0

  • scikit-learn==1.1.3

  • scipy==1.9.3

  • setuptools==49.1.3

  • six==1.16.0

  • statsmodels==0.13.5

  • subprocess32==3.5.4

  • sympy==1.8

  • tbats==1.1.0

  • threadpoolctl==3.1.0

  • tqdm==4.64.1

  • typing_extensions==4.4.0

  • urllib3==1.25.11

  • wheel==0.37.0

  • wrapt==1.14.1

  • yarl==1.8.2

  • zipp==3.10.0

AWS Glue version 3.0

AWS Glue 버전 3.0은 기본적으로 다음과 같은 Python 모듈을 포함합니다.

  • aiobotocore==1.4.2

  • aiohttp==3.8.3

  • aioitertools==0.11.0

  • aiosignal==1.3.1

  • async-timeout==4.0.2

  • asynctest==0.13.0

  • attrs==22.2.0

  • avro-python3==1.10.2

  • boto3==1.18.50

  • botocore==1.21.50

  • certifi==2021.5.30

  • chardet==3.0.4

  • charset-normalizer==2.1.1

  • click==8.1.3

  • cycler==0.10.0

  • Cython==0.29.4

  • docutils==0.17.1

  • enum34==1.1.10

  • frozenlist==1.3.3

  • fsspec==2021.8.1

  • idna==2.10

  • importlib-metadata==6.0.0

  • jmespath==0.10.0

  • joblib==1.0.1

  • kiwisolver==1.3.2

  • matplotlib==3.4.3

  • mpmath==1.2.1

  • multidict==6.0.4

  • nltk==3.6.3

  • numpy==1.19.5

  • packaging==23.0

  • pandas==1.3.2

  • patsy==0.5.1

  • Pillow==9.4.0

  • pip==23.0

  • pmdarima==1.8.2

  • ptvsd==4.3.2

  • pyarrow==5.0.0

  • pydevd==2.5.0

  • pyhocon==0.3.58

  • PyMySQL==1.0.2

  • pyparsing==2.4.7

  • python-dateutil==2.8.2

  • pytz==2021.1

  • PyYAML==5.4.1

  • regex==2022.10.31

  • requests==2.23.0

  • s3fs==2021.8.1

  • s3transfer==0.5.0

  • scikit-learn==0.24.2

  • scipy==1.7.1

  • six==1.16.0

  • Spark==1.0

  • statsmodels==0.12.2

  • subprocess32==3.5.4

  • sympy==1.8

  • tbats==1.1.0

  • threadpoolctl==3.1.0

  • tqdm==4.64.1

  • typing_extensions==4.4.0

  • urllib3==1.25.11

  • wheel==0.37.0

  • wrapt==1.14.1

  • yarl==1.8.2

  • zipp==3.12.0

AWS Glue version 2.0

AWS Glue 버전 2.0은 기본적으로 다음과 같은 Python 모듈을 포함합니다.

  • avro-python3==1.10.0

  • awscli==1.27.60

  • boto3==1.12.4

  • botocore==1.15.4

  • certifi==2019.11.28

  • chardet==3.0.4

  • click==8.1.3

  • colorama==0.4.4

  • cycler==0.10.0

  • Cython==0.29.15

  • docutils==0.15.2

  • enum34==1.1.9

  • fsspec==0.6.2

  • idna==2.9

  • importlib-metadata==6.0.0

  • jmespath==0.9.4

  • joblib==0.14.1

  • kiwisolver==1.1.0

  • matplotlib==3.1.3

  • mpmath==1.1.0

  • nltk==3.5

  • numpy==1.18.1

  • pandas==1.0.1

  • patsy==0.5.1

  • pmdarima==1.5.3

  • ptvsd==4.3.2

  • pyarrow==0.16.0

  • pyasn1==0.4.8

  • pydevd==1.9.0

  • pyhocon==0.3.54

  • PyMySQL==0.9.3

  • pyparsing==2.4.6

  • python-dateutil==2.8.1

  • pytz==2019.3

  • PyYAML==5.3.1

  • regex==2022.10.31

  • requests==2.23.0

  • rsa==4.7.2

  • s3fs==0.4.0

  • s3transfer==0.3.3

  • scikit-learn==0.22.1

  • scipy==1.4.1

  • setuptools==45.2.0

  • six==1.14.0

  • Spark==1.0

  • statsmodels==0.11.1

  • subprocess32==3.5.4

  • sympy==1.5.1

  • tbats==1.0.9

  • tqdm==4.64.1

  • typing-extensions==4.4.0

  • urllib3==1.25.8

  • wheel==0.35.1

  • zipp==3.12.0