Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 738 – 지원 플랫폼으로서의 Android 추가

Author:
Malcolm Smith <smith at chaquo.com>
Sponsor:
Petr Viktorin <encukou at gmail.com>
Discussions-To:
Discourse thread
Status:
Final
Type:
Standards Track
Created:
12-Dec-2023
Python-Version:
3.13
Resolution:
Discourse message

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

Important

This PEP is a historical document. The up-to-date, canonical documentation can now be found at Using Python on Android.

×

See PEP 1 for how to propose changes.

초록

이 PEP는 CPython에 지원 플랫폼으로 Android를 추가할 것을 제안합니다. 초기 목표는 Python 3.13에서 Android가 Tier 3 지원을 달성하도록 하는 것입니다.

이 PEP는 Russell Keith-Magee가 작성한 PEP 730 – “지원 플랫폼으로서의 iOS 추가”에 기반하며, 동일한 문제를 많이 다룹니다. 두 플랫폼 간의 주목할 만한 차이점은 “iOS”라는 단어를 검색하면 찾을 수 있습니다.

동기

지난 15년 동안 모바일 플랫폼은 컴퓨팅 환경에서 점점 더 중요한 부분이 되었습니다. Android는 이러한 기기의 약 70%에서 실행되는 운영 체제입니다. 그러나 CPython에는 Android에 대한 공식 지원이 없습니다.

Chaquopy, BeeWareKivy 프로젝트는 모두 수년 동안 Android를 지원해 왔으며, Google Play 스토어에 게시가 승인된 애플리케이션을 생성하는 데 모두 사용되었습니다. 이는 Android 지원의 기술적 실현 가능성을 입증합니다.

Python이라는 언어의 미래를 위해서는 널리 채택된 모든 플랫폼에서 Python을 사용할 수 있는 것이 중요합니다. 그렇지 않으면 잠재적 사용자는 이러한 플랫폼을 실제로 지원하는 다른 언어를 선택할 것입니다. 이는 교육 분야에서 특히 그러하며, 차세대 개발자는 많은 경우 이미 데스크톱 플랫폼보다 모바일 플랫폼을 사용하는 데 더 많은 시간을 보내고 있습니다.

근거

일반 사항

Android는 Linux 커널과 ELF 바이너리 형식을 기반으로 하는 광의의 POSIX 플랫폼입니다. Android는 glibc를 사용하지 않고, 대신 Bionic이라는 자체 C 라이브러리 구현을 제공합니다. 그 결과 아키텍처가 일치하더라도 일반적으로 다른 어떤 Linux 배포판과도 바이너리 호환되지 않습니다. 또한 다른 어떤 Unix와도 닮지 않은 자체 파일 시스템 배치를 사용합니다.

그러나 Android의 Linux와의 소스 호환성은 상당히 우수합니다. 초기에는 C 라이브러리가 매우 불완전했지만, 대략 그 무렵까지 대부분의 격차가 해소되었지만, 2014. 그 이후로는 Linux용으로 컴파일되는 모든 C 코드를 대체로 하드웨어 장치 또는 운영 체제 서비스에 직접 액세스하는 경우를 제외하면 Android용으로 컴파일할 수 있습니다.

이는 CPython에도 해당합니다. 공식적으로 Android를 지원한 적은 없지만, 최근 버전(3.6 이후)은 최소한의 패치만으로도 이미 Android용으로 컴파일할 수 있습니다.

OS 버전

각 Android 버전은 세 가지 방식으로 식별할 수 있습니다.

  • 일반적인 점으로 구분된 버전 번호(최근 버전은 모두 정수를 사용했지만)
  • 순차적인 정수 “API 레벨”(개발자 문서에서 가장 일반적인 형식)
  • 알파벳순의 제과 관련 코드명(더 이상 마케팅에는 사용되지 않지만 개발자 문서에는 여전히 나타남)

이들 중 하나를 다른 하나와 연결하는 일관된 패턴이 없으므로, a table에서 찾아보아야 합니다.

매년 새로운 주요 Android 버전이 출시되지만, 각 장치에 제공되는 업데이트는 전적으로 해당 제조업체의 통제를 받습니다. 안타깝게도 많은 제조업체는 사용자가 장치를 처분할 준비가 되기 훨씬 전에 장치에 업데이트를 보내는 일을 중단합니다. 예를 들어 2023년 10월 기준으로 보안 업데이트를 계속 받고 있던 가장 오래된 Android 버전은 API 레벨 30이었지만, Google’s own statistics에 따르면 장치 중 해당 버전 이상을 사용하는 비율은 60%에 불과했습니다.

따라서 Python 3.13에서는 2014년에 출시된 Android 5.0(API 레벨 21)을 최소 Android 버전으로 제안합니다. 위 통계에 따르면 이는 활성 장치의 99%를 지원할 수 있습니다.

개발 도구

Android 개발 도구는 Linux(x86_64), Windows(x86_64) 및 macOS(x86_64 및 ARM64)에서 동일하게 지원됩니다. CPython에서 가장 중요한 도구는 다음과 같습니다.

  • NDK(네이티브 개발 키트)에는 모든 시스템 라이브러리를 위한 C 및 C++ 컴파일러(clang), 링커(lld) 및 헤더가 포함되어 있습니다.

    서로 다른 NDK 버전으로 컴파일된 라이브러리 간의 바이너리 호환성은 일반적으로 매우 우수하지만, 재현성을 위해서는 각 Python 버전이 수명 전체에 걸쳐 하나의 NDK 버전을 사용하는 것이 가장 좋습니다. Python 3.13에서는 현재 NDK 장기 지원 버전인 r26이 이에 해당합니다.

    각 NDK 버전은 광범위한 Android 버전 중 어느 것이든 대상으로 설정할 수 있습니다. 예를 들어 NDK r26은 API levels 21부터 34까지 지원합니다. 그러나 이전 Android 버전용으로 컴파일된 바이너리는 일반적으로 이후 버전에서도 무기한 계속 작동하며, 이 규칙의 예외는 보안상의 이유로만 적용됩니다.

  • Gradle은 완전하게 배포할 수 있는 앱을 빌드하는 데 사용되는 도구입니다.
  • QEMU를 기반으로 하는 에뮬레이터는 개발 머신에서 실행되는 시뮬레이션된 Android 장치입니다. iOS와 달리 에뮬레이터는 동일한 아키텍처의 실제 장치와 같은 ABI를 사용하며 동일한 바이너리를 실행할 수 있습니다.

이러한 도구는 모두 명령줄에서 사용하거나 IntelliJ IDEA를 기반으로 하는 Android Studio IDE를 통해 사용할 수 있습니다.

아키텍처

Android는 현재 4개의 아키텍처를 지원합니다. Android 도구에서 사용하는 이름은 다음과 같습니다.

  • armeabi-v7a
  • arm64-v8a
  • x86
  • x86_64

현재 출시되는 물리적 장치의 거의 전부는 ARM 아키텍처 중 하나를 사용합니다. x86x86_64는 에뮬레이터에서 사용하도록 지원됩니다.

Python 3.13에서는 Tier 3 지원이 64비트 플랫폼(arm64-v8ax86_64)만 포함하도록 제안합니다.

  • x86은 2020년 이후 개발 플랫폼으로 지원되지 않았으며, 그 이후 새로운 에뮬레이터 이미지는 출시되지 않았습니다.
  • armeabi-v7a의 활성 장치 비율은 현재 10% 미만이며 꾸준히 감소하고 있습니다.

    또한 신뢰할 수 있는 빌드봇으로 지원하기도 더 어려울 것입니다. 에뮬레이터에 사용할 수 있는 네이티브 호스트가 없기 때문입니다(ARM64 Mac에는 ARM32 코드를 위한 하드웨어 지원이 없습니다). 아키텍처 간 에뮬레이션도 가능하지만 성능과 안정성이 훨씬 떨어지므로 armeabi-v7a 에뮬레이터 이미지는 2016년 이후 업데이트되지 않았습니다.

    그러나 시계와 초저가 휴대폰에서는 계속 사용됩니다. 이러한 상황이 지속된다면 향후 Python 버전에 이를 추가하는 것을 고려해야 할 수 있습니다.

32비트 아키텍처가 공식적으로 지원되지 않더라도, 여전히 이를 빌드하려는 다운스트림 프로젝트를 방해할 수 있는 변경은 수행해서는 안 됩니다.

앱 수명 주기

Android 앱의 주요 프로그래밍 언어는 Java 또는 그 현대적 후계자인 Kotlin입니다. 따라서 앱은 자체 실행 파일을 제공하지 않습니다. 대신 모든 앱은 운영 체제가 제공하는 실행 파일을 실행하는 Java 가상 머신으로 시작합니다. 그러면 앱의 Java 코드는 동적 라이브러리를 로드하고 JNI를 통해 이를 호출하여 프로세스에 네이티브 코드를 추가할 수 있습니다.

iOS와 달리 하위 프로세스 생성은 Android에서 지원됩니다. 그러나 앱은 특정 위치에서만 실행 파일을 실행할 수 있으며, 그중 어느 곳도 런타임에 쓰기 가능하지 않습니다. 장시간 실행되는 하위 프로세스는 공식적으로 권장되지 않음이며, 향후 Android 버전에서 지원된다는 보장도 없습니다.

Android는 명령줄 셸을 제공하지만, 이는 개발자만 사용하도록 설계되었으며 일반 최종 사용자는 사용할 수 없습니다.

이러한 이유로 Android에서 Python을 실행하는 권장 방법은 동적 libpython3.x.so 라이브러리를 주 앱 프로세스에 로드하는 것입니다. 이 플랫폼에서는 python3.x 실행 파일을 공식적으로 지원하지 않습니다.

사양

작업 범위

이 작업의 초점은 기존의 Windows 임베디드 패키지에 해당하는 Android용 패키지, 즉 개발자가 앱에 추가할 수 있는 컴파일된 라이브러리 집합을 만드는 것입니다. 설치 프로그램은 필요하지 않습니다.

Android를 Tier 3 플랫폼으로 추가하려면 패치되지 않은 CPython 소스 코드에서 Android 호환 빌드를 컴파일할 수 있도록 지원을 추가하기만 하면 됩니다. 반드시 python.org에 공식적으로 배포되는 Android 아티팩트가 있어야 하는 것은 아니지만, 향후 이를 추가할 수는 있습니다.

Android는 다른 POSIX 플랫폼과 동일한 configure 및 Makefile 시스템을 사용하여 빌드되므로 POSIX 플랫폼에서 빌드되어야 합니다. Linux와 macOS가 모두 지원됩니다.

CPython 테스트 스위트를 실행하기 위한 Gradle 프로젝트가 제공됩니다. 테스트 스위트 앱 빌드, 에뮬레이터 시작, 테스트 스위트 설치 및 실행 과정을 자동화하는 도구가 제공됩니다.

링키지

App lifecycle에서 논의한 이유로 인해 Python은 dlopen을 사용하여 앱에 로드할 수 있는 동적 libpython3.x.so 라이브러리로 앱에 포함됩니다.

Linux와 달리 Android는 RTLD_GLOBAL을 사용하더라도후속 로드되는 라이브러리의 재배치를 해결하는 데 dlopened 라이브러리를 암묵적으로 사용하지 않습니다. 따라서 Android용으로 빌드할 때 모든 Python 확장 모듈은 libpython3.x.so에 명시적으로 링크되어야 합니다.

libpython3.x.so에 링크된 확장 모듈은 libpython3.x.a에 정적으로 링크된 실행 파일에서 로드할 수 없습니다. 따라서 Android에서는 정적 libpython3.x.a 라이브러리를 지원하지 않습니다. 이는 CPython이 Windows에서 사용하는 것과 동일한 패턴입니다.

이 접근 방식을 사용하면 빌드 시 누락된 기호를 감지하기 위해 -Wl,--no-undefined옵션을 사용할 수도 있으며, 이는 상당한 시간을 절약할 수 있습니다.

iOS와 달리 Android에서는 동적 라이브러리를 어느 위치에서든 로드할 수 있으므로, .py, .pyc 및 .so 파일이 함께 배치된 디렉터리 트리를 Python의 표준 임포터로 처리할 수 있습니다.

표준 라이브러리

지원되지 않는 모듈

기반 C API를 사용할 수 없으므로 Android에서는 여러 표준 라이브러리 모듈을 지원하지 않습니다:

  • cursesreadline
  • dbm.gnudbm.ndbm
  • grp
  • multiprocessing – 일반적으로 하위 프로세스는 허용되지만(App lifecycle 참조), Android에서는 System V IPC API의 어떤 부분도 지원하지 않습니다.
  • tkinterturtle – 이를 사용하려면 Tk 자체의 Android 빌드가 필요하며, 이는 공식적으로 지원되지 않습니다.

sys

sys.platform"android"를 반환합니다. Android는 Linux를 기반으로 하지만 충분히 중요한 차이가 있으므로 별도의 이름을 사용하는 것이 타당합니다.

Android 앱에 내장된 경우 C 수준의 stdio 스트림은 아무것에도 연결되지 않습니다. 따라서 이 모드에서는 sys.stdoutsys.stderr는 시스템 Logcat으로 리디렉션되며, Android 개발 도구로 이를 확인할 수 있습니다. sys.stdin은 항상 EOF를 반환합니다.

platform

platform 모듈이 반환하는 대부분의 값은 다음 예외를 제외하면 os.uname()이 반환하는 값과 일치합니다:

  • platform.system() - 기본 "Linux" 대신 "Android"
  • platform.release() - Linux 커널 버전 대신 문자열로 표시된 Android 버전 번호(예: "14")

또한 다음을 포함하는 namedtuple을 반환하는 platform.android_ver() 메서드가 추가됩니다:

  • release - 문자열로 표시된 장치의 Android 버전(예: "14")
  • api_level - 정수로 표시된 장치의 API level(예: 34)
  • manufacturer - 문자열로 표시된 장치의 manufacturer(예: "Google")
  • model - 문자열로 표시된 장치의 model name(예: "Pixel 7")
  • device - 문자열로 표시된 장치의 device name(예: "panther")
  • is_emulator - 장치가 에뮬레이터이면 True이고, 실제 장치이면 False입니다.

modeldevice중 어느 것이 고유할 가능성이 더 높은지, 어느 것이 마케팅 이름과 더 유사할 가능성이 더 높은지는 제조업체마다 다릅니다.

os

os.uname()은 POSIX uname() 호출의 원시 결과를 반환합니다. 그 결과 다음과 같은 값이 반환됩니다:

  • sysname - "Linux"
  • release - Linux 커널 버전(예: "5.10.157-android13-4-00003-gdfb1120f912b-ab10994928")

이 접근 방식에서는 os 모듈을 시스템 API에 대한 “원시” 인터페이스로, platform을 더 일반적으로 유용한 값을 제공하는 고수준 API로 취급합니다.

CI 리소스

Android 에뮬레이터와 실제 장치는 동일한 ABI를 사용하고 동일하거나 매우 유사한 운영 체제 바이너리를 제공하므로, 에뮬레이터에서 테스트하는 것으로 충분합니다. x86_64 에뮬레이터는 Linux, macOS 또는 Windows에서 실행할 수 있지만, ARM64 에뮬레이터는 ARM64 Mac에서만 지원됩니다.

Anaconda는 Android 빌드봇을 실행할 물리적 하드웨어를 제공하겠다고 제안했습니다. 여기에는 Linux x86_64 머신과 macOS ARM64 머신이 모두 포함되므로, 지원되는 런타임 아키텍처와 지원되는 빌드 플랫폼을 모두 아우를 수 있습니다.

CPython은 현재 GitHub Actions에서 Tier 3 플랫폼을 테스트하지 않지만, 향후 이러한 상황이 바뀐다면 Linux 및 macOS 러너에서도 Android 에뮬레이터를 호스팅할 수 있습니다. macOS ARM64 러너는 2024년 1월부터 모든 공개 저장소에 무료로 제공되어 왔습니다.

패키징

Android 휠은 android_<api-level>_<abi> 형식의 태그를 사용합니다. 예를 들면 다음과 같습니다.

  • android_21_arm64_v8a
  • android_21_x86_64

<api-level>의 의미는 OS versions를 참조하십시오. 휠 태그의 맥락에서 이는 휠을 컴파일할 때 선택된 최소 Android 버전을 나타냅니다. pip와 같은 설치 도구는 기존 macOS 태그와 유사한 방식으로 이를 해석해야 합니다. 즉, 최소 API 레벨이 N인 앱은 API 레벨이 N이거나 그보다 오래된 것으로 태그된 휠을 포함할 수 있습니다.

이 형식은 현재 API 레벨 16부터 21까지 다양한 태그를 사용하는 Chaquopy 프로젝트에서 비롯되었습니다.

그러나 소수의 Android 애호가 그룹에 전체 Python 생태계의 빌드를 의존하는 것은 확장 가능한 해결책이 아닙니다. 주요 라이브러리들이 자체 Android 휠을 정기적으로 릴리스할 때까지 커뮤니티가 Android에서 Python을 채택할 수 있는 역량은 제한될 것입니다.

따라서 프로젝트가 CI 및 릴리스 도구에 Android 빌드를 추가하는 방법을 명확히 문서화해야 합니다. crossenvcibuildwheel과 같은 도구에 Android 지원을 추가하는 것이 이를 달성하는 한 가지 방법일 수 있습니다.

Android 휠 태그 형식도 PyPI에서 허용하는 태그 목록에 추가해야 합니다.

PEP 11 업데이트

PEP 11은 지원되는 두 Android ABI를 포함하도록 업데이트됩니다. Autoconf는 이미 다음 트리플릿으로 이를 식별합니다.

  • aarch64-linux-android
  • x86_64-linux-android

Petr Viktorin이 이러한 ABI를 담당하는 최초의 코어 팀 연락 담당자 역할을 맡습니다.

하위 호환성

새 플랫폼을 추가해도 CPython 자체에는 하위 호환성 문제가 발생하지 않습니다. 그러나 최종 CPython 패치 형태가 해당 프로젝트에서 역사적으로 사용해 온 패치와 일치하지 않는 경우, 역사적으로 CPython 지원을 제공해 온 프로젝트(즉, BeeWare 및 Kivy)에는 일부 하위 호환성 영향이 있을 수 있습니다.

보안 영향

새 플랫폼을 추가해도 새로운 보안 영향은 발생하지 않습니다.

이 내용을 가르치는 방법

이 PEP와 관련된 교육 요구 사항은 두 개발자 그룹과 관련됩니다.

먼저, apps 개발자는 자신의 Python 코드 및 지원 패키지와 함께 Python을 Android 앱에 빌드하는 방법과 런타임에 이를 모두 사용하는 방법을 알아야 합니다. 문서에서는 기존 Windows embeddable package와 유사한 형태로 이를 다룹니다. 그러나 대부분의 개발자에게 이미 포괄적인 문서가 제공되는 Briefcase, ChaquopyBuildozer와 같은 고수준 도구를 사용하도록 권장합니다.

둘째, 바이너리 구성 요소를 포함하는 packages의 개발자는 Android용으로 이를 빌드하고 릴리스하는 방법을 알아야 합니다(Packaging을 참조하십시오).

참조 구현

Chaquopy repository에는 참조 패치와 빌드 스크립트가 포함되어 있습니다. 이를 업스트림에 반영하려면 먼저 Chaquopy의 다른 구성 요소와 분리해야 합니다.

Briefcase는 Android 장치와 에뮬레이터에서 테스트 스위트를 실행하는 코드의 참조 구현을 제공합니다. Toga Testbed는 GitHub Actions를 사용하여 Android 에뮬레이터에서 실행되는 테스트 스위트의 예입니다.

기각된 아이디어

platform.android_ver()의 원래 사양에 다음과 같은 변경이 이루어졌습니다.

  • min_api_level 필드는 다른 모든 필드와 달리 현재 장치의 속성이 아니기 때문에 제거되었습니다. 이 정보는 기존에 존재하던 함수 sys.getandroidapilevel()를 통해 여전히 사용할 수 있습니다.
  • 테스트 중 일부 문제가 에뮬레이터에만 해당하는 것으로 나타났기 때문에 is_emulator 필드가 추가되었습니다.