> **Источник:** https://python-all.ru/3/using/ios.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 7. Использование Python на iOS

**Авторы:**

Russell Keith-Magee (2024-03)

Python на iOS отличается от Python на настольных платформах. На настольной платформе Python обычно устанавливается как системный ресурс, доступный любому пользователю этого компьютера. Пользователи взаимодействуют с Python, запуская **python** и вводя команды в интерактивном режиме или запуская сценарии Python.

В iOS нет понятия установки как системного ресурса. Единственная единица распространения программного обеспечения – это «приложение». Также здесь нет консоли, в которой можно запустить **python** или работать с REPL Python.

Поэтому единственный способ использовать Python на iOS – это встраивание: нужно написать нативное приложение iOS и встроить в него интерпретатор Python с помощью `libPython`, а затем вызывать код Python через [API встраивания Python](https://python-all.ru/3/extending/embedding.html#embedding). Полный интерпретатор Python, стандартная библиотека и весь ваш код Python упаковываются в отдельный пакет, который можно распространять через App Store.

Если вы впервые пробуете написать приложение для iOS на Python, такие проекты, как [BeeWare](https://python-all.ru/3/using/ios.html) и [Kivy](https://python-all.ru/3/using/ios.html), предоставят гораздо более простой пользовательский опыт. Они берут на себя все сложности запуска проекта под iOS, так что вам нужно работать только с кодом Python.

## 7.1. Python во время выполнения на iOS

### 7.1.1. Совместимость с версиями iOS

Минимальная поддерживаемая версия iOS задаётся на этапе компиляции с помощью параметра [`--host`](https://python-all.ru/3/using/configure.html#cmdoption-host) для `configure`. По умолчанию при сборке для iOS Python компилируется с минимальной поддерживаемой версией 13.0. Чтобы использовать другую минимальную версию iOS, укажите номер версии в аргументе `--host` – например, `--host=arm64-apple-ios15.4-simulator` соберёт сборку для симулятора ARM64 с целевой версией 15.4.

### 7.1.2. Определение платформы

При выполнении на iOS `sys.platform` возвращает `ios`. Это значение возвращается на iPhone или iPad независимо от того, запущено ли приложение на симуляторе или физическом устройстве.

Информацию о конкретной среде выполнения, включая версию iOS, модель устройства и то, является ли оно симулятором, можно получить с помощью [`platform.ios_ver()`](https://python-all.ru/3/library/platform.html#platform.ios_ver). [`platform.system()`](https://python-all.ru/3/library/platform.html#platform.system) вернёт `iOS` или `iPadOS` в зависимости от устройства.

[`os.uname()`](https://python-all.ru/3/library/os.html#os.uname) сообщает детали на уровне ядра; он вернёт имя `Darwin`.

### 7.1.3. Доступность стандартной библиотеки

Стандартная библиотека Python имеет некоторые заметные пропуски и ограничения на iOS. Подробнее см. в [руководстве по доступности API для iOS](https://python-all.ru/3/library/intro.html#mobile-availability).

### 7.1.4. Двоичные модули расширения

Одно из ключевых отличий iOS как платформы – распространение через App Store налагает жёсткие требования к упаковке приложения. Одно из них касается того, как распространяются двоичные модули расширения.

App Store требует, чтобы *все* двоичные модули в приложении iOS были динамическими библиотеками, помещёнными во фреймворк с соответствующими метаданными и расположенными в папке `Frameworks` упакованного приложения. Во фреймворке может быть только один двоичный файл, и никаких исполняемых двоичных материалов за пределами папки `Frameworks` быть не должно.

Это противоречит обычному подходу Python к распространению двоичных файлов, который позволяет загружать двоичный модуль расширения из любого места на `sys.path`. Чтобы соответствовать политикам App Store, проект iOS должен постобработать все пакеты Python, преобразовав двоичные модули `.so` в отдельные автономные фреймворки с соответствующими метаданными и подписью. Подробнее о том, как выполнить эту постобработку, см. в руководстве [по добавлению Python в ваш проект](https://python-all.ru/3/using/ios.html#adding-ios).

Чтобы помочь Python находить двоичные файлы в новом расположении, исходный файл `.so` на `sys.path` заменяется файлом `.fwork`. Этот файл – текстовый файл, содержащий путь к фреймворку относительно пакета приложения. Чтобы фреймворк мог разрешать обратно исходное расположение, он должен содержать файл `.origin` с путём к файлу `.fwork` относительно пакета приложения.

Например, рассмотрим случай импорта `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`.

При запуске на iOS интерпретатор Python устанавливает [`AppleFrameworkLoader`](https://python-all.ru/3/library/importlib.html#importlib.machinery.AppleFrameworkLoader), который умеет читать и импортировать файлы `.fwork`. После импорта атрибут `__file__` двоичного модуля будет указывать на расположение файла `.fwork`. Однако [`ModuleSpec`](https://python-all.ru/3/library/importlib.html#importlib.machinery.ModuleSpec) для загруженного модуля будет сообщать `origin` как расположение двоичного файла в папке фреймворка.

### 7.1.5. Компиляторные заглушки

Xcode не предоставляет явные компиляторы для iOS; вместо этого он использует скрипт `xcrun`, который разрешается в полный путь к компилятору (например, `xcrun --sdk iphoneos clang` для получения `clang` для устройства iPhone). Однако использование этого скрипта создаёт две проблемы:

- Вывод команды `xcrun` содержит пути, зависящие от конкретной машины, из-за чего модуль sysconfig невозможно использовать совместно между пользователями;
- Это приводит к определениям `CC`/`CPP`/`LD`/`AR`, содержащим пробелы. Многие инструменты экосистемы C предполагают, что можно разделить командную строку по первому пробелу, чтобы получить путь к исполняемому файлу компилятора; при использовании `xcrun` это не так.

Чтобы избежать этих проблем, Python предоставляет заглушки для этих инструментов. Эти заглушки представляют собой обёртки в виде сценариев оболочки вокруг базовых инструментов `xcrun`, распространяемые в папке `bin` вместе со скомпилированным фреймворком iOS. Эти сценарии являются перемещаемыми и всегда разрешаются в соответствующие локальные системные пути. Включение этих сценариев в папку bin, сопровождающую фреймворк, делает содержимое модуля `sysconfig` полезным для конечных пользователей, собирающих собственные модули. При компиляции сторонних модулей Python для iOS убедитесь, что эти заглушки находятся в вашем PATH.

## 7.2. Установка Python на iOS

### 7.2.1. Инструменты для сборки iOS-приложений

Сборка для iOS требует использования инструментов Apple Xcode. Настоятельно рекомендуется использовать самую последнюю стабильную версию Xcode. Для этого потребуется самая последняя (или предпоследняя) версия macOS, так как Apple не поддерживает Xcode для старых версий macOS. Для разработки под iOS недостаточно утилит Xcode Command Line Tools; необходима *полная* установка Xcode.

Если вы хотите запустить свой код на симуляторе iOS, вам также потребуется установить платформу симулятора iOS. При первом запуске Xcode вам будет предложено выбрать платформу симулятора iOS. Кроме того, платформу симулятора iOS можно добавить, выбрав её на вкладке Platforms панели настроек Xcode.

### 7.2.2. Добавление Python в проект iOS

Python можно добавить в любой проект iOS, используя Swift или Objective C. В следующих примерах будет использоваться Objective C; если вы используете Swift, вам может пригодиться библиотека вроде [PythonKit](https://python-all.ru/3/using/ios.html).

Чтобы добавить Python в проект iOS Xcode:

1. Соберите или получите Python `XCFramework`. См. инструкции в [Apple/iOS/README.md](https://python-all.ru/src/3.14/Apple/iOS/README.md) (в дистрибутиве исходных кодов CPython) для подробностей о том, как собрать Python `XCFramework`. Как минимум потребуется сборка, поддерживающая `arm64-apple-ios`, а также один из `arm64-apple-ios-simulator` или `x86_64-apple-ios-simulator`.
2. Перетащите `XCframework` в свой проект iOS. В следующих инструкциях мы будем считать, что вы поместили `XCframework` в корень проекта; однако вы можете использовать любое другое расположение, скорректировав пути по необходимости.
3. Добавьте код вашего приложения как папку в проект Xcode. В следующих инструкциях мы будем считать, что ваш пользовательский код находится в папке с именем `app` в корне проекта; вы можете использовать любое другое расположение, скорректировав пути по необходимости. Убедитесь, что эта папка связана с вашей целью приложения.
4. Выберите цель приложения, выбрав корневой узел вашего проекта Xcode, а затем имя цели на появившейся боковой панели.
5. В настройках “General”, в разделе “Frameworks, Libraries and Embedded Content”, добавьте `Python.xcframework`, выбрав “Embed & Sign”.
6. На вкладке “Build Settings” измените следующие параметры:

   - Параметры сборки

     - User Script Sandboxing: Нет
     - Enable Testability: Да
   - Пути поиска

     - Framework Search Paths: `$(PROJECT_DIR)`
     - Header Search Paths: `"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"`
   - Apple Clang - Warnings - All languages

     - Quoted Include In Framework Header: Нет
7. Добавьте шаг сборки, который обрабатывает стандартную библиотеку Python и ваши собственные бинарные зависимости Python. На вкладке “Build Phases” добавьте новый шаг сборки “Run Script” *до* шага “Embed Frameworks”, но *после* шага “Copy Bundle Resources”. Назовите шаг “Process Python libraries”, отключите флажок “Based on dependency analysis” и задайте содержимое скрипта:

   ```bash
   set -e
   source $PROJECT_DIR/Python.xcframework/build/build_utils.sh
   install_python Python.xcframework app
   ```

   Если вы разместили ваш XCframework не в корне проекта, измените путь в первом аргументе.
8. Добавьте код на Objective C для инициализации и использования интерпретатора Python во встроенном режиме. Следует убедиться, что:

   - Режим UTF-8 ([`PyPreConfig.utf8_mode`](https://python-all.ru/3/c-api/init_config.html#c.PyPreConfig.utf8_mode)) *включён*;
   - Буферизированный stdio ([`PyConfig.buffered_stdio`](https://python-all.ru/3/c-api/init_config.html#c.PyConfig.buffered_stdio)) *отключён*;
   - Запись байт-кода ([`PyConfig.write_bytecode`](https://python-all.ru/3/c-api/init_config.html#c.PyConfig.write_bytecode)) *отключена*;
   - Обработчики сигналов ([`PyConfig.install_signal_handlers`](https://python-all.ru/3/c-api/init_config.html#c.PyConfig.install_signal_handlers)) *включены*;
   - Системное журналирование ([`PyConfig.use_system_logger`](https://python-all.ru/3/c-api/init_config.html#c.PyConfig.use_system_logger)) *включено* (необязательно, но настоятельно рекомендуется; включено по умолчанию);
   - [`PYTHONHOME`](https://python-all.ru/3/using/cmdline.html#envvar-PYTHONHOME) для интерпретатора настроены указывать на подпапку `python` пакета вашего приложения; и
   - [`PYTHONPATH`](https://python-all.ru/3/using/cmdline.html#envvar-PYTHONPATH) для интерпретатора включает:

     - подпапку `python/lib/python3.X` пакета вашего приложения,
     - подпапка `python/lib/python3.X/lib-dynload` в составе пакета приложения и
     - подпапка `app` в составе пакета приложения

   Расположение пакета вашего приложения можно определить с помощью `[[NSBundle mainBundle] resourcePath]`.

Шаги 7 и 8 данной инструкции предполагают, что у вас есть одна папка с чистым кодом приложения на Python, названная `app`. Если в вашем приложении есть сторонние бинарные модули, потребуются дополнительные действия:

- Необходимо убедиться, что все папки, содержащие сторонние бинарные файлы, либо связаны с целевой платформой приложения, либо явно скопированы на шаге 7. На шаге 7 также следует удалить все бинарные файлы, не подходящие для платформы, под которую собирается конкретная сборка (например, удалить бинарные файлы для устройства, если собирается приложение для симулятора).
- Если вы используете отдельную папку для сторонних пакетов, убедитесь, что эта папка добавлена в конец вызова `install_python` на шаге 7, а также как часть конфигурации [`PYTHONPATH`](https://python-all.ru/3/using/cmdline.html#envvar-PYTHONPATH) на шаге 8.
- Если какая-либо из папок, содержащих сторонние пакеты, будет содержать файлы `.pth`, следует добавить эту папку как *каталог сайта* (с помощью [`site.addsitedir()`](https://python-all.ru/3/library/site.html#site.addsitedir)), а не добавлять напрямую к [`PYTHONPATH`](https://python-all.ru/3/using/cmdline.html#envvar-PYTHONPATH) или [`sys.path`](https://python-all.ru/3/library/sys.html#sys.path).

### 7.2.3. Тестирование пакета Python

Дерево исходных кодов CPython содержит [тестовый проект](https://python-all.ru/3/using/ios.html), который используется для запуска тестового набора CPython в симуляторе iOS. Этот тестовый проект также можно использовать для запуска тестов вашей библиотеки Python на iOS.

После сборки или получения XCFramework для iOS (см. [Apple/iOS/README.md](https://python-all.ru/src/3.14/Apple/iOS/README.md) для подробностей), создайте клон тестового проекта Python для iOS. Если вы использовали скрипт сборки `Apple` для создания XCFramework, можно выполнить:

```bash
$ python cross-build/iOS/testbed clone --app <path/to/module1> --app <path/to/module2> app-testbed
```

Или, если вы получили свой собственный XCFramework, выполнив:

```bash
$ python Apple/testbed clone --platform iOS --framework <path/to/Python.xcframework> --app <path/to/module1> --app <path/to/module2> app-testbed
```

Все папки, указанные с помощью флага `--app`, будут скопированы в клонированный тестовый проект. Полученный тестовый проект будет создан в папке `app-testbed`. В этом примере `module1` и `module2` будут импортируемыми модулями во время выполнения. Если у вашего проекта есть дополнительные зависимости, их можно установить в папку `app-testbed/Testbed/app_packages` (используя `pip install --target app-testbed/Testbed/app_packages` или аналогичный инструмент).

Затем можно использовать папку `app-testbed` для запуска тестового набора вашего приложения. Например, если `module1.tests` была точкой входа вашего тестового набора, можно выполнить:

```bash
$ python app-testbed run -- module1.tests
```

Это эквивалентно запуску `python -m module1.tests` в настольной сборке Python. Все аргументы после `--` будут переданы тестовому проекту так, как если бы они были аргументами для `python -m` на настольной машине.

Тестовый проект также можно открыть в Xcode, выполнив:

```bash
$ open app-testbed/iOSTestbed.xcodeproj
```

Это позволит использовать полный набор инструментов Xcode для отладки.

Аргументы, используемые для запуска тестового набора, определяются в рамках тестового плана. Чтобы изменить тестовый план, выберите узел тестового плана в дереве проекта (это должен быть первый дочерний элемент корневого узла) и выберите вкладку «Configurations». Измените значение «Arguments Passed On Launch», чтобы изменить аргументы тестирования.

Тестовый план также отключает параллельное тестирование и предписывает использование файла `Testbed.lldbinit` для настройки отладчика. Конфигурация отладчика по умолчанию отключает автоматические точки останова на сигналы `SIGINT`, `SIGUSR1`, `SIGUSR2` и `SIGXFSZ`.

## 7.3. Соответствие требованиям App Store

Единственный механизм распространения приложений на сторонние устройства iOS – это отправка приложения в App Store; приложения, отправленные на распространение, должны пройти процесс проверки приложений Apple. Этот процесс включает набор автоматических правил проверки, которые анализируют отправленный пакет приложения на наличие проблемного кода. Необходимо предпринять некоторые шаги, чтобы ваше приложение могло пройти эти проверки.

### 7.3.1. Несовместимый код в стандартной библиотеке

Стандартная библиотека Python содержит код, который, как известно, нарушает эти автоматические правила. Хотя эти нарушения кажутся ложными срабатываниями, правила проверки Apple не подлежат обжалованию; поэтому необходимо модифицировать стандартную библиотеку Python, чтобы приложение прошло проверку App Store.

Дерево исходных кодов Python содержит [файл исправлений](https://python-all.ru/src/3.14/Mac/Resources/app-store-compliance.patch), который удалит весь код, вызывающий проблемы в процессе проверки App Store. Это исправление применяется автоматически при сборке для iOS.

### 7.3.2. Манифесты конфиденциальности

В апреле 2025 года Apple ввела требование для [определенных сторонних библиотек предоставлять манифест конфиденциальности](https://python-all.ru/3/using/ios.html). В результате, если у вас есть бинарный модуль, использующий одну из затронутых библиотек, вы должны предоставить файл `.xcprivacy` для этой библиотеки. OpenSSL – одна из библиотек, на которые распространяется это требование, но есть и другие.

Если вы создаете бинарный модуль с именем `mymodule.so` и используете скрипт сборки Xcode, описанный на шаге 7 выше, вы можете разместить файл `mymodule.xcprivacy` рядом с `mymodule.so`, и манифест конфиденциальности будет установлен в требуемое место при преобразовании бинарного модуля в framework.
