Документация Python неофициальный перевод

ios.md

223 строк · 30.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.13/using/ios.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 7. Использование Python на iOS89**Авторы:**1011Russell Keith-Magee (2024-03)1213Python на iOS отличается от Python на настольных платформах. На настольной платформе Python обычно устанавливается как системный ресурс, доступный любому пользователю этого компьютера. Пользователи взаимодействуют с Python, запуская **python** и вводя команды в интерактивном режиме или запуская сценарии Python.1415В iOS нет понятия установки как системного ресурса. Единственная единица распространения программного обеспечения – это «приложение». Также здесь нет консоли, в которой можно запустить **python** или работать с REPL Python.1617Поэтому единственный способ использовать Python на iOS – это встраивание: нужно написать нативное приложение iOS и встроить в него интерпретатор Python с помощью `libPython`, а затем вызывать код Python через [API встраивания Python](https://python-all.ru/3.13/extending/embedding.html#embedding). Полный интерпретатор Python, стандартная библиотека и весь ваш код Python упаковываются в отдельный пакет, который можно распространять через App Store.1819Если вы впервые пробуете написать приложение для iOS на Python, такие проекты, как [BeeWare](https://python-all.ru/3.13/using/ios.html) и [Kivy](https://python-all.ru/3.13/using/ios.html), предоставят гораздо более простой пользовательский опыт. Они берут на себя все сложности запуска проекта под iOS, так что вам нужно работать только с кодом Python.2021## 7.1. Python во время выполнения на iOS2223### 7.1.1. Совместимость с версиями iOS2425Минимальная поддерживаемая версия iOS задаётся на этапе компиляции с помощью параметра [`--host`](https://python-all.ru/3.13/using/configure.html#cmdoption-host) для `configure`. По умолчанию при сборке для iOS Python компилируется с минимальной поддерживаемой версией 13.0. Чтобы использовать другую минимальную версию iOS, укажите номер версии в аргументе `--host` – например, `--host=arm64-apple-ios15.4-simulator` соберёт сборку для симулятора ARM64 с целевой версией 15.4.2627### 7.1.2. Определение платформы2829При выполнении на iOS `sys.platform` возвращает `ios`. Это значение возвращается на iPhone или iPad независимо от того, запущено ли приложение на симуляторе или физическом устройстве.3031Информацию о конкретной среде выполнения, включая версию iOS, модель устройства и то, является ли оно симулятором, можно получить с помощью [`platform.ios_ver()`](https://python-all.ru/3.13/library/platform.html#platform.ios_ver). [`platform.system()`](https://python-all.ru/3.13/library/platform.html#platform.system) вернёт `iOS` или `iPadOS` в зависимости от устройства.3233[`os.uname()`](https://python-all.ru/3.13/library/os.html#os.uname) сообщает детали на уровне ядра; он вернёт имя `Darwin`.3435### 7.1.3. Доступность стандартной библиотеки3637Стандартная библиотека Python имеет некоторые заметные пропуски и ограничения на iOS. Подробнее см. в [руководстве по доступности API для iOS](https://python-all.ru/3.13/library/intro.html#mobile-availability).3839### 7.1.4. Двоичные модули расширения4041Одно из ключевых отличий iOS как платформы – распространение через App Store налагает жёсткие требования к упаковке приложения. Одно из них касается того, как распространяются двоичные модули расширения.4243App Store требует, чтобы *все* двоичные модули в приложении iOS были динамическими библиотеками, помещёнными во фреймворк с соответствующими метаданными и расположенными в папке `Frameworks` упакованного приложения. Во фреймворке может быть только один двоичный файл, и никаких исполняемых двоичных материалов за пределами папки `Frameworks` быть не должно.4445Это противоречит обычному подходу Python к распространению двоичных файлов, который позволяет загружать двоичный модуль расширения из любого места на `sys.path`. Чтобы соответствовать политикам App Store, проект iOS должен постобработать все пакеты Python, преобразовав двоичные модули `.so` в отдельные автономные фреймворки с соответствующими метаданными и подписью. Подробнее о том, как выполнить эту постобработку, см. в руководстве [по добавлению Python в ваш проект](https://python-all.ru/3.13/using/ios.html#adding-ios).4647Чтобы помочь Python находить двоичные файлы в новом расположении, исходный файл `.so` на `sys.path` заменяется файлом `.fwork`. Этот файл – текстовый файл, содержащий путь к фреймворку относительно пакета приложения. Чтобы фреймворк мог разрешать обратно исходное расположение, он должен содержать файл `.origin` с путём к файлу `.fwork` относительно пакета приложения.4849Например, рассмотрим случай импорта `from foo.bar import _whiz`, где `_whiz` реализован двоичным модулем `sources/foo/bar/_whiz.abi3.so`, а `sources` – это расположение, зарегистрированное на `sys.path`, относительно пакета приложения. Этот модуль *должен* распространяться как `Frameworks/foo.bar._whiz.framework/foo.bar._whiz` (название фреймворка образуется из полного пути импорта модуля), с файлом `Info.plist` в каталоге `.framework`, идентифицирующим двоичный файл как фреймворк. Модуль `foo.bar._whiz` будет представлен в исходном расположении маркерным файлом `sources/foo/bar/_whiz.abi3.fwork`, содержащим путь `Frameworks/foo.bar._whiz/foo.bar._whiz`. Фреймворк также будет содержать `Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin` с путём к файлу `.fwork`.5051При запуске на iOS интерпретатор Python устанавливает [`AppleFrameworkLoader`](https://python-all.ru/3.13/library/importlib.html#importlib.machinery.AppleFrameworkLoader), который умеет читать и импортировать файлы `.fwork`. После импорта атрибут `__file__` двоичного модуля будет указывать на расположение файла `.fwork`. Однако [`ModuleSpec`](https://python-all.ru/3.13/library/importlib.html#importlib.machinery.ModuleSpec) для загруженного модуля будет сообщать `origin` как расположение двоичного файла в папке фреймворка.5253### 7.1.5. Компиляторные заглушки5455Xcode не предоставляет явные компиляторы для iOS; вместо этого он использует скрипт `xcrun`, который разрешается в полный путь к компилятору (например, `xcrun --sdk iphoneos clang` для получения `clang` для устройства iPhone). Однако использование этого скрипта создаёт две проблемы:5657- Вывод команды `xcrun` содержит пути, зависящие от конкретной машины, из-за чего модуль sysconfig невозможно использовать совместно между пользователями;58- Это приводит к определениям `CC`/`CPP`/`LD`/`AR`, содержащим пробелы. Многие инструменты экосистемы C предполагают, что можно разделить командную строку по первому пробелу, чтобы получить путь к исполняемому файлу компилятора; при использовании `xcrun` это не так.5960Чтобы избежать этих проблем, Python предоставляет заглушки для этих инструментов. Эти заглушки представляют собой обёртки в виде сценариев оболочки вокруг базовых инструментов `xcrun`, распространяемые в папке `bin` вместе со скомпилированным фреймворком iOS. Эти сценарии являются перемещаемыми и всегда разрешаются в соответствующие локальные системные пути. Включение этих сценариев в папку bin, сопровождающую фреймворк, делает содержимое модуля `sysconfig` полезным для конечных пользователей, собирающих собственные модули. При компиляции сторонних модулей Python для iOS убедитесь, что эти заглушки находятся в вашем PATH.6162## 7.2. Установка Python на iOS6364### 7.2.1. Инструменты для сборки iOS-приложений6566Сборка для iOS требует использования инструментов Apple Xcode. Настоятельно рекомендуется использовать самую последнюю стабильную версию Xcode. Для этого потребуется самая последняя (или предпоследняя) версия macOS, так как Apple не поддерживает Xcode для старых версий macOS. Для разработки под iOS недостаточно утилит Xcode Command Line Tools; необходима *полная* установка Xcode.6768Если вы хотите запустить свой код на симуляторе iOS, вам также потребуется установить платформу симулятора iOS. При первом запуске Xcode вам будет предложено выбрать платформу симулятора iOS. Кроме того, платформу симулятора iOS можно добавить, выбрав её на вкладке Platforms панели настроек Xcode.6970### 7.2.2. Добавление Python в проект iOS7172Python можно добавить в любой проект iOS, используя Swift или Objective C. В следующих примерах будет использоваться Objective C; если вы используете Swift, вам может пригодиться библиотека вроде [PythonKit](https://python-all.ru/3.13/using/ios.html).7374Чтобы добавить Python в проект iOS Xcode:75761. Соберите или получите Python `XCFramework`. Инструкции по сборке Python `XCFramework` см. в [iOS/README.rst](https://python-all.ru/src/3.13/iOS/README.rst) (в дистрибутиве исходного кода CPython). Как минимум потребуется сборка, поддерживающая `arm64-apple-ios` и один из вариантов: `arm64-apple-ios-simulator` или `x86_64-apple-ios-simulator`.772. Перетащите `XCframework` в свой проект iOS. В следующих инструкциях мы будем считать, что вы поместили `XCframework` в корень проекта; однако вы можете использовать любое другое расположение, скорректировав пути по необходимости.783. Перетащите файл `iOS/Resources/dylib-Info-template.plist` в проект и убедитесь, что он связан с целью приложения.794. Добавьте код вашего приложения как папку в проект Xcode. В следующих инструкциях мы будем считать, что ваш пользовательский код находится в папке с именем `app` в корне проекта; вы можете использовать любое другое расположение, скорректировав пути по необходимости. Убедитесь, что эта папка связана с вашей целью приложения.805. Выберите цель приложения, выбрав корневой узел вашего проекта Xcode, а затем имя цели на появившейся боковой панели.816. В настройках “General”, в разделе “Frameworks, Libraries and Embedded Content”, добавьте `Python.xcframework`, выбрав “Embed & Sign”.827. На вкладке “Build Settings” измените следующие параметры:8384   - Параметры сборки8586     - User Script Sandboxing: Нет87     - Enable Testability: Да88   - Пути поиска8990     - Пути поиска фреймворков: `$(PROJECT_DIR)`91     - Пути поиска заголовков: `"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"`92   - Apple Clang - Предупреждения - Все языки9394     - Quoted Include In Framework Header: Нет958. Добавьте шаг сборки, копирующий стандартную библиотеку Python в приложение. На вкладке «Build Phases» добавьте новый шаг сборки «Run Script» *перед* шагом «Embed Frameworks», но *после* шага «Copy Bundle Resources». Назовите шаг «Install Target Specific Python Standard Library», снимите флажок «Based on dependency analysis» и задайте содержимое скрипта:9697   ```bash98   set -e99100   mkdir -p "$CODESIGNING_FOLDER_PATH/python/lib"101   if [ "$EFFECTIVE_PLATFORM_NAME" = "-iphonesimulator" ]; then102       echo "Installing Python modules for iOS Simulator"103       rsync -au --delete "$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"104   else105       echo "Installing Python modules for iOS Device"106       rsync -au --delete "$PROJECT_DIR/Python.xcframework/ios-arm64/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"107   fi108   ```109110   Обратите внимание, что имя «среза» симулятора в XCframework может отличаться в зависимости от архитектур процессора, которые поддерживает ваша `XCFramework`.1119. Добавьте второй шаг сборки, преобразующий двоичные модули расширения из стандартной библиотеки в формат «Framework». Добавьте шаг сборки «Run Script» *непосредственно после* шага, добавленного на шаге 8, и назовите его «Prepare Python Binary Modules». У него также должен быть снят флажок «Based on dependency analysis», а содержимое скрипта должно быть следующим:112113   ```bash114   set -e115116   install_dylib () {117       INSTALL_BASE=$1118       FULL_EXT=$2119120       # Имя файла расширения121       EXT=$(basename "$FULL_EXT")122       # Расположение файла расширения относительно пакета123       RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/}124       # Путь к файлу расширения относительно базовой установки125       PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}126       # Полное точечное имя модуля расширения, построенное из пути к файлу.127       FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d "." -f 1 | tr "/" ".");128       # Идентификатор пакета; на самом деле не используется, но требуется для упаковки фреймворка Xcode129       FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr "_" "-")130       # Имя папки фреймворка.131       FRAMEWORK_FOLDER="Frameworks/$FULL_MODULE_NAME.framework"132133       # Если папка фреймворка не существует, создайте её.134       if [ ! -d "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ]; then135           echo "Creating framework for $RELATIVE_EXT"136           mkdir -p "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER"137           cp "$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"138           plutil -replace CFBundleExecutable -string "$FULL_MODULE_NAME" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"139           plutil -replace CFBundleIdentifier -string "$FRAMEWORK_BUNDLE_ID" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"140       fi141142       echo "Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME"143       mv "$FULL_EXT" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME"144       # Создаёт файл-заполнитель .fwork в том месте, где находился .so145       echo "$FRAMEWORK_FOLDER/$FULL_MODULE_NAME" > ${FULL_EXT%.so}.fwork146       # Создаёт обратную ссылку на местоположение файла .so в фреймворке147       echo "${RELATIVE_EXT%.so}.fwork" > "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin"148    }149150    PYTHON_VER=$(ls -1 "$CODESIGNING_FOLDER_PATH/python/lib")151    echo "Install Python $PYTHON_VER standard library extension modules..."152    find "$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload" -name "*.so" | while read FULL_EXT; do153       install_dylib python/lib/$PYTHON_VER/lib-dynload/ "$FULL_EXT"154    done155156    # Очищает шаблон dylib157    rm -f "$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist"158159    echo "Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..."160    find "$CODESIGNING_FOLDER_PATH/Frameworks" -name "*.framework" -exec /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "{}" \;161   ```16210. Добавьте код на Objective C для инициализации и использования интерпретатора Python во встроенном режиме. Следует убедиться, что:163164> - Режим UTF-8 ([`PyPreConfig.utf8_mode`](https://python-all.ru/3.13/c-api/init_config.html#c.PyPreConfig.utf8_mode)) *включён*;165> - Буферизированный stdio ([`PyConfig.buffered_stdio`](https://python-all.ru/3.13/c-api/init_config.html#c.PyConfig.buffered_stdio)) *отключён*;166> - Запись байт-кода ([`PyConfig.write_bytecode`](https://python-all.ru/3.13/c-api/init_config.html#c.PyConfig.write_bytecode)) *отключена*;167> - Обработчики сигналов ([`PyConfig.install_signal_handlers`](https://python-all.ru/3.13/c-api/init_config.html#c.PyConfig.install_signal_handlers)) *включены*;168> - [`PYTHONHOME`](https://python-all.ru/3.13/using/cmdline.html#envvar-PYTHONHOME) для интерпретатора настроены указывать на подпапку `python` пакета вашего приложения; и169> - [`PYTHONPATH`](https://python-all.ru/3.13/using/cmdline.html#envvar-PYTHONPATH) для интерпретатора включает:170>171>   - подпапку `python/lib/python3.X` пакета вашего приложения,172>   - подпапка `python/lib/python3.X/lib-dynload` в составе пакета приложения и173>   - подпапка `app` в составе пакета приложения174>175> Расположение пакета вашего приложения можно определить с помощью `[[NSBundle mainBundle] resourcePath]`.176177Шаги 8, 9 и 10 этой инструкции предполагают, что у вас есть единственная папка с чистым кодом приложения на Python с именем `app`. Если в вашем приложении есть сторонние двоичные модули, потребуются дополнительные шаги:178179- Необходимо убедиться, что все папки, содержащие сторонние двоичные файлы, либо связаны с целью приложения, либо скопированы на шаге 8. Шаг 8 также должен удалять все двоичные файлы, не подходящие для платформы, на которую ориентирована конкретная сборка (например, удалять двоичные файлы для устройства, если собирается приложение для симулятора).180- Все папки, содержащие сторонние двоичные файлы, должны быть преобразованы в форму фреймворка на шаге 9. Вызов `install_dylib`, обрабатывающий папку `lib-dynload`, можно скопировать и адаптировать для этой цели.181- Если используется отдельная папка для сторонних пакетов, убедитесь, что она включена в конфигурацию [`PYTHONPATH`](https://python-all.ru/3.13/using/cmdline.html#envvar-PYTHONPATH) на шаге 10.182- Если какая-либо из папок, содержащих сторонние пакеты, будет содержать файлы `.pth`, следует добавить эту папку как *каталог сайта* (с помощью [`site.addsitedir()`](https://python-all.ru/3.13/library/site.html#site.addsitedir)), а не добавлять напрямую к [`PYTHONPATH`](https://python-all.ru/3.13/using/cmdline.html#envvar-PYTHONPATH) или [`sys.path`](https://python-all.ru/3.13/library/sys.html#sys.path).183184### 7.2.3. Тестирование пакета Python185186Дерево исходных кодов CPython содержит [тестовый проект](https://python-all.ru/3.13/using/ios.html), который используется для запуска тестового набора CPython в симуляторе iOS. Этот тестовый проект также можно использовать для запуска тестов вашей библиотеки Python на iOS.187188После сборки или получения iOS XCFramework (подробнее см. [iOS/README.rst](https://python-all.ru/src/3.13/iOS/README.rst)) создайте клон тестового проекта Python iOS, выполнив:189190```bash191$ python iOS/testbed clone --framework <path/to/Python.xcframework> --app <path/to/module1> --app <path/to/module2> app-testbed192```193194Вам нужно изменить ссылку `iOS/testbed` так, чтобы она указывала на этот каталог в дереве исходников CPython; все папки, указанные с флагом `--app`, будут скопированы в клонированный тестовый проект. Полученный тестовый проект будет создан в папке `app-testbed`. В этом примере `module1` и `module2` будут импортируемыми модулями во время выполнения. Если в вашем проекте есть дополнительные зависимости, их можно установить в папку `app-testbed/iOSTestbed/app_packages` (с помощью `pip install --target app-testbed/iOSTestbed/app_packages` или аналогичного инструмента).195196Затем можно использовать папку `app-testbed` для запуска тестового набора вашего приложения. Например, если `module1.tests` была точкой входа вашего тестового набора, можно выполнить:197198```bash199$ python app-testbed run -- module1.tests200```201202Это эквивалентно запуску `python -m module1.tests` в настольной сборке Python. Все аргументы после `--` будут переданы тестовому проекту так, как если бы они были аргументами для `python -m` на настольной машине.203204Тестовый проект также можно открыть в Xcode, выполнив:205206```bash207$ open app-testbed/iOSTestbed.xcodeproj208```209210Это позволит использовать полный набор инструментов Xcode для отладки.211212Аргументы, используемые для запуска тестового набора, определяются в рамках тестового плана. Чтобы изменить тестовый план, выберите узел тестового плана в дереве проекта (это должен быть первый дочерний элемент корневого узла) и выберите вкладку «Configurations». Измените значение «Arguments Passed On Launch», чтобы изменить аргументы тестирования.213214Тестовый план также отключает параллельное тестирование и предписывает использование файла `iOSTestbed.lldbinit` для настройки отладчика. Конфигурация отладчика по умолчанию отключает автоматические точки останова на сигналы `SIGINT`, `SIGUSR1`, `SIGUSR2` и `SIGXFSZ`.215216## 7.3. Соответствие требованиям App Store217218Единственный механизм распространения приложений на сторонние устройства iOS – это отправка приложения в App Store; приложения, отправленные на распространение, должны пройти процесс проверки приложений Apple. Этот процесс включает набор автоматических правил проверки, которые анализируют отправленный пакет приложения на наличие проблемного кода.219220Стандартная библиотека Python содержит код, который, как известно, нарушает эти автоматические правила. Хотя эти нарушения кажутся ложными срабатываниями, правила проверки Apple не подлежат обжалованию; поэтому необходимо модифицировать стандартную библиотеку Python, чтобы приложение прошло проверку App Store.221222Дерево исходных кодов Python содержит [файл исправлений](https://python-all.ru/src/3.13/Mac/Resources/app-store-compliance.patch), который удалит весь код, вызывающий проблемы в процессе проверки App Store. Это исправление применяется автоматически при сборке для iOS.223