Пакет Python для разгрузки функционального вызова на HTTP -сервер, работающий на LocalHost, автоматически с помощью декоратора. Совместим с многопроцестрой, маринованными, колбами, Fastapi, Async и т. Д.
Представьте себе случай многопоточного или многопроцессорного приложения, где 1 или несколько функций являются интенсивными ресурсами (ЦП или памятью), но другие функции могут работать параллельно.
Пример - вызов API с последующей токенизацией и классификацией с использованием большой DL -модели с последующей дальнейшими вызовами API.
В таком случае было бы имеет смысл создать сервер (обычно с использованием TorchServe или TFServing) для обслуживания запросов, и заменить вызов функции с помощью запроса POST на сервер.
ServerHandler создает синхронный сервер и автоматически заменяет любые вызовы функции во время выполнения.
Запросы выполняются в 1 экземпляре процесса, запускающего http.server.httpserver, который запускает функцию внутри нее.
Также доступен AsyncServerHandler, что делает запросы асинхронно.
Даже вызовы, сделанные из разных процессов, потоков, многопроцестрой, колбы, FASTAPI и Async Tycops, выполняются в одном и том же серверном процессе.
В общем :
some code with a callable
может быть заменен экземпляром либо ServerHandler, либо AsyncServerHandler, который принимает код как строку в его первом аргументе, и имя вызывшего в качестве второго аргумента.
from auto_function_serving . ServerHandler import ServerHandler
callable_name = ServerHandler ( """
some independent code with a callable
""" , "callable_name" )Пример :
import module1
import module2
def functionname ( someinput ):
a = module1 . function1 ( someinput )
return module2 . function2 ( a )можно заменить на
from auto_function_serving . ServerHandler import AsyncserverHandler
functionname = AsyncServerHandler ( """
import module1
import module2
def functionname(someinput):
a = module1.function1(someinput)
return module2.function2(a)
""" , "functionname" , port = "Any" )Декораторы ( @asyncserverhandler.decorator и @serverhandler.decorator) и Asyncserverhandler в большем количестве использования.
from auto_function_serving . ServerHandler import ServerHandler
callable_name = ServerHandler ( """
some independent code with a callable
""" , "callable_name" , port = None , backend = 'Popen' , wait = 100 , backlog = 1024 )) Запускает http.server.httpserver.
Объекты ServerHandler и AsyncServerHandler могут быть загружены и разгружены с помощью Pickle.
Использует Popen или многопроцесс, чтобы запустить сервер.
Использует только одну внешнюю зависимость (AIOHTTP) и только для Async.
http, не https.
Выбирает порт на основе хэша ввода. (Если не указано иное)
Минимальные изменения кода.
Должен быть совместимы почти со всеми функциями почти во всех ветвях CPYTHON. (Не уверен, где это может потерпеть неудачу? Пожалуйста, добавьте проблему, если вы найдете ее.)
Утечки памяти или ошибки (с сервера) крайне маловероятны, поскольку они минимальны, однопоточный, единый процесс и компонент по умолчанию Python stdlib.
Исключения приводят к ошибкам 5xx без закрытия сервера.
Даже отдельные процессы сделают запросы на 1 экземпляры того же сервера, если не указано иное. (Потому что он ищет сервер на определенном порту.).
Можно указать иное, установив порт в любой бесплатный порт, чтобы новый объект ServerHandler запустил новый сервер.
HTTP POST Запросы: легкие, мало накладных расходов MS, надежные.
Async - хорошая особенность.
Теперь с тестами.
Наличие строки кода в качестве аргумента для класса не является питоническим, если только декоратор не используется.
Импорт внутренних функций не идеален, даже когда используется декоратор.
http post Запросы: небезопасно, мало накладных расходов MS.
Исключения внутри сервера не отправляются обратно.
Нет партии.
Нет встроенного регистрации. (Может быть добавлен). Запуск инициализации в течение нескольких секунд для запуска сервера. Асинхронные функции не будут работать на сервере.
Нет автоматического перезапуска в случае, если сервер закрывается.
Может оставить некоторые ресурсы заблокированными на некоторое время (<1 мин), если не закрыты должным образом.
Проблемы могут возникнуть, если Popen или Multiprocessing не доступны.
Возможные вложенные асинхронные ошибки с Юпитером или другим? Пожалуйста, посмотрите на гнездо и проблемы.
Предупреждения от несколько взломанных (но законных и совершенно функциональных) обходных путей.
Закрытие серверного процесса в del и atexit.redister ( del ) по какой -то причине не удастся (протестировано и маловероятно).
Используйте диспетчер пакетов PIP для установки auto_function_serving
pip install auto_function_serving Код для сервера хранится в ServerHandler.base_Code, и некоторые формирование строки используется для заполнения пробелов.
Серверный процесс запускается с Popen (или многопроцестрой, если указано). Первое, что он делает, - это импортировать сокет и связывать порт - если он недоступен, код останавливается после исключения. Поэтому только 1 экземпляр сервера работает одновременно на машине.
Мы знаем, что функция готова после того, как мы сможем получить действительный запрос GET от сервера.
Входные данные и выходы отправляются в виде байтов, преобразуемых в объекты и обратно с использованием рассола.
Если порт не находится во время инициализации (по умолчанию), порт от 50000 до 60000 выбирается путем хэширования входного кода, чтобы сделать его независимым от источника функции. Столкновения различных функций возможны, но маловероятны. Столкновение одной и той же функции в нескольких процессах используется, чтобы убедиться, что только 1 серверный процесс работает за раз. Порт может быть указан при необходимости.
Накладные расходы за небольшой вход и вывод (несколько байтов) -
~ 2 мс для запросов с urllib.request
~ 4 мс для асинхронных запросов с aiohttp.clientsession
накладные расходы на большой вход и вывод
~ 10 мс для входа и выхода 0,5 МБ (общая передача 1 МБ).
~ 60 мс для входа и выхода 5 МБ (общая передача 10 МБ).
~ 600 мс для входа и выхода 50 МБ (общая передача 100 МБ).
Его также можно использовать с предоставленным декоратором для функций без зависимостей вне функции.
from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
for i in range ( big_number )
someexpensivecomputationимпорт внутри функции будет работать
from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
import numpy as np from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
if not hasattr ( someheavyfunction , 'RunOnce' ):
global np
import numpy as np
setattr ( someheavyfunction , 'RunOnce' , None )
... etcКогда у Somemodule нет дорогой глобальной загрузки.
from auto_function_serving . ServerHandler import ServerHandler
from somemodule import someheavyfunction
someheavyfunction = ServerHandler . decorator ( someheavyfunction )IP -адрес может быть изменен, установив ServerHandler.ip_address (по умолчанию "127.0.0.1") перед созданием нового экземпляра.
Также доступен AsyncServerHandler, который использует AIOHTTP для выполнения запросов асинхронно, для использования с FASTAPI и другими асинхронными вариантами использования.
AsyncServerHandler имеет такое же использование, что и ServerHandler, за исключением случаев, когда вызовы должны быть ожидаются или использовать с Asyncio.run () или с Asyncio.get_event_loop (). Run_until_complete ().
Количество Async -вызовов может быть ограничено путем установки AsyncServerHandler.tcpconnector_limit, который управляет пределом TCPConnector (по умолчанию 100). Использование Semaphore также является чем -то, что нужно рассмотреть.
Библиотеки: сельдерей, Tfserving, Torchserve, Flask
Отправка глобалов и местных жителей в Exec
Аст Деревья
Приглашаются запросы.
Apache License 2.0