.. SimpleUI documentation master file, created by sphinx-quickstart on Sat May 16 14:23:51 2020. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Python в обработчиках ======================= Приложения Simple UI могут использовать интерпретатор Python для выполнения кода обработчиков в любом режиме. Можно писать код обработчиков используя процедуры, классы, библиотеки. Перечень библиотек и актуальная версия интерпретатора может меняться от релиза к релизу и информация об этом будет обновляться. На текущий момент используется: * Версия Python - 3.11 (для сборки с OpenCV+PyTorch – версия 3.8) Подключены библиотеки: * Стандартные библиотеки * Requests * Lxml * pony * Pillow * Jinja2 * python-barcode * pymongo * qrcode * tinydb * tinyrecord * zpl * escpos-gen * pelicandbms * python-dateutil Так как GooglePlay не позволяет публиковать пакеты больше 100 Мб, то периодически, в виде отдельных сборок apk публикуется сборка с: * Pandas * BeautifulSoup * OpenCV * Pytorch * torchvision Взаимодействие Python-обработчиков с платформой и интерфейсом происходит через стек перменных (объект hashMap), слайсы, а также объекты напрямую – Датасеты, СУБД, файлы, прямой вызов функций платформы hashMap (стек переменных) – объект, через который передаются переменные и т.н. комманды-переменные (ShowScreen, FinishProcess и т.д.). Это не python-словарь, как можно было бы подумать, а Java-объект HashMap. Обращение к нему происходит через указанные методы: * put(ключ,значение) – поместить переменную * get(ключ) – получить переменную * remove(ключ) – удалить переменную * containsKey(ключ) – проверить, есть ли такой ключ в коллекции Причем с точки зрения выполнения, сам стек (и команды в нем) анализируются в конце обработчика, то есть интерпретируется обработчик (со всему put, remove), потом система читает ключи в стеке и выполняет комманды. Есть несколько видов python-обработчиков с разным назначением. Тип обработчика pythonscript ---------------------------------- Самый простой обработчик. Выполняется как excec(<код обработчика>). Нигде не хранится, по сути, это строка, запускаемая на интерпретацию. Из этого исходит тот факт, что между вызовами этого обработчика также не хранятся и переменные. Это похоже на JavaScript. Это можно было бы сравнить с запуском скриптов в разных терминалах. Отличительной особенность данного обработчика- сам скрипт в виде base64 храниться в массиве обработчиков в method и редактируется непосредственно в окне конструкторе. Это упрощает работу с небольшими скриптами и лучше структурирует архитектуру обработчиков. Все примеры написаны с использованием этого типа обработчиков .. note:: Simple стремиться к простоте и минимальности кода, поэтому вместо нагромождения модулей, рекомендуется ограничиваться небольшими скриптами 10-15 строк на одно событие В обработчик заходят: * hashMap – стек перменных * process_slice – слайс процесса (на чтение) * screen_slice – слайс экрана (на чтение) Также подключены: 1) Функция **get_body** которые позволяет в упрощенном режиме вырезать код из текущего обработчика для запуска обработчиков (например RunEvent или для download) Пример .. code-block:: Python def after_download_1(): with open(hashMap.get("DownloadedFile"), encoding='utf-8-sig') as f: toast("Загрузили файл : "+hashMap.get("DownloadedFile")) hashMap.put("RestartScreen","") postExecute = json_to_str([{"action": "run", "type": "pythonscript","method":get_body(after_download_1) }]) su.download(download_url,None,None,'goods.txt',postExecute) 2) функции **json_to_str** и **str_to_json** оберки для json.dumps(j,ensure_ascii=False, indent=4) и json.loads(s) 3) функции для работы с датасетами: * CreateDataSet(name,options=None) * GetDataSet(name) * DeleteDataSet(name) 4) Функция GetDataSetData 5) Функция SendBus для отправки в шину Модули: * **android** – функции системы, такие как toast,beep,speak и т.д. * **json** * **base64** Переменные: * **_local** – key-value СУБД (см. раздел Хранение) * **_data_dir** , **_downloads_dir** – папки конфигурации для внутреннего хранения Общий модуль general ~~~~~~~~~~~~~~~~~~~~~~~~ Также в конструкторе (в разделе Конфигурация) доступен для редактирования модуль general. Его поведение в системе несколько отличается. Он сохраняется в файл при загрузке конфигурации и доступен через import general. В этом модуле можно хранить общие функции и переменные. Тип обработчика python ------------------------- В отличии от pytonscript эти обработчики при загрузке в конфигурацию сохраняются в файл handlers_conf.py, далее из этого модуля идет вызов функций. Т.е. в method в массиве обработчиков храниться не сам текст скрипта, а имя функции, которая запускается из модуля. Обработчики такого типа (также как и pythonargs и pythonbytes) подключаются в конфигурацию в виде файлов. Должен быть как минимум файл обработчиков (это вызовы функций, объявляемых в массиве обработчиков), он пишется в конфигурацию в PyHandlers. Плюс может быть один или несколько подключаемых модулей. Они пишутся в массив PyFiles конфигурации .. code-block:: JSON "PyFiles": [ { "PyFileKey": "ext", "PyFileData": "base64-содержимое файла" } ] Все файлы при загрузке конфигурации сохраняются в файлы в внутренней папке. Дополнительные файлы можно импортировать по ключу (они сохраняются в ту же папку с именем .py В пользовательском режиме все это сохранение происходит через конструктор. Это можно сделтаь на закладке Файлы модулей: * либо через обычную загрузку файлов (Загрузить основной py-файл, Добавить дополнительный Py-файл). При этом способе придется проделывать это действие при каждом изменении в файлах python * либо подключив GitHub(инструкция на странице конструктора). Доступно и открытый и закрытый репозиторий. Этот способ хорош тем, что также к репозиторию можно подключить ваше IDE и коммиты будут автоматически сохранться из IDE и при сохранении конфигурации. Кстати, саму конфигурацию (ui) также можно сохранять на GitHub (закладка Пользователь). Этот способ удобнее. **Когда нужно использовать python, а когда pythonscript?** Приблизительно будет верным ответ, что python надо использовать в больших проектах, с более чем одним python-модулем. Для простых проектов всетаки предпочтительнее pythonscript. Функции этого типа должны иметь определенный формат: .. code-block:: Python def foo(hashMap,_files=None,_data=None): hashMap.put("toast",hashMap.get("barcode")) #пример записи в стек и чтения из стека return hashMap **_data** – для SUIP-файлов, данные, упакованные в файл **_files** – устарело, но нужно указывать для совместимости Функции, с произвольным числом аргументов pythonargs ----------------------------------------------------- картинка Можно использовать функции с произвольным числом неименованных аргументов (обычно называют args). Для этого надо выбрать в настройке обработчика **pythonargs** Пример кода такого обработчика: .. code-block:: Python def foo(hashMap,*args): param1 = args[0] param2 = args[1] param3 = args[2] return hashMap Функция для работы с OpenCV pythonbytes -------------------------------------------- При захвате изображения для дальнейшего анализа в OpenCV в обработчик передается изображение в виде byte-массива. Обработчики имеют следующий формат: .. code-block:: Python def detect_face(hashMap,imageBytes): np_data = np.asarray(imageBytes,np.uint8) img = cv2.imdecode(np_data,cv2.IMREAD_UNCHANGED) #Тут работа с изображением return hashMap Функции платформы, которые работают run-time (модуль android) ---------------------------------------------------------------------- Все функции доступны через команды-переменные, но часто это не совсем удобно. Например, надо вывести тост внутри долгого обработчика или обновлять уведомление внутри цикла, а не после выполнения такта обработчика (а стек-машина выполняет команды-переменные по окончанию такта). Это именно run-time на уровне системы, т.е. выполняется непосредственно в момент вызова. Все подобные функции собраны в модуль вpython- модуль android и их можно использовать так: .. code-block:: Python import android android.toast("hello") Интерфейсные команды: * toast(String toast) – вывести сообщение Андроид * speak(String text) – произнести текст (TTS engine) * listen() – запустить ожидание распознавания речи * vibrate() и vibrate(int duration) – вибрация и вибрация заданной длительности * beep()/beep(int tone)/ beep(int tone,int beep_duration,int beep_volume) – звуковой сигнал, т.ч. с возможностью выбрать тон (от 1 до 99), продолжительность и громкость (по умолчанию – 100) * notification(String message)/ notification (String message,String title)/ notification(String message,String title,int number) – уведомление в шторке уведомлений. Number – идентификатор уведомления, по которому к нему можно потом обратиться, чтобы либо убрать, либо перезаписать (обновить) * notification_progress(String message,String title,int number,int progress) – уведомление с прогресс-баром (от 0 до 100) notification_cancel(int number) – скрыть уведомление Управляющие команды: * refresh_screen() запускает рефреш экрана. Предполагается, что стек будет установлен рантайм методами работы со стеком * refresh_screen(hashMap) - запускает рефреш и передает стек. * RunEvent(String handlers) – запустить массив обработчиков * BackgroundCommand(command) – запустить фоновую команду * stop() или stop(hashMap) – точка останова для отладки Работа со стеком: * get_process_hashmap() – получает стек переменных экрана из любого места * get_cv_hashmap() – получает стек переменных ActiveCV из любого места * get_service_hashmap() – получает стек переменных фонового сервиса из любого места * process_started() – получает признак, запущен ли процесс в данный момент * cv_started() – получает признак, запущено ли ActiveCV в данный момент * put_process_hashMap(key,value) помещает значение в стек процесса * remove_process_hashMap(key) – удаляет значение из стека процесса Дополгнительные Java-модули, доступные из Python-обработчиков -------------------------------------------------------------------- Вообще, правильнее будет сказать что из Python-Обработчиков доступны люые Java-классы. Но практическую ценность имеют некоторые из них. Класс ImportUtils (from ru.travelfood.simple_ui import ImportUtils as iu): * getView(String tag) – получить Java-объект виджета по его переменной (и после, делать все что хочется его методами) * getContext() – получить контекст (контекст может понадобится в других функциях SDK) * getRootLayout() – получить корневой контейнер экрана Модуль SimpleUtilites(from ru.travelfood.simple_ui import SimpleUtilites as su): * get_stored_file(String key) – получить абсолютный путь к медиафайлу по ключу * download(String url,String user,String password,String filename,String postExecute) – запустить загрузку в воркере с прогресс-баром (пример выше). По окончании выполняется обработчик postExecute * deleteCache() – удаляет кеш приложения