Ein Python -Paket zum Ableiten eines Funktionsaufrufs auf einen HTTP -Server, der mit einem Dekorator automatisch auf Localhost ausgeführt wird. Kompatibel mit Multiprocessing, Gurke, Flask, Fastapi, Async usw.
Stellen Sie sich einen Fall einer Mehrfaden- oder Multiprozessing -Anwendung vor, bei der 1 oder wenige Funktionen stark intensiv sind, aber die anderen Funktionen können parallel ausgeführt werden.
Beispiel - Ein API -Aufruf, gefolgt von Tokenisierung und Klassifizierung unter Verwendung eines großen DL -Modells, gefolgt von weiteren API -Aufrufen.
In einem solchen Fall wäre es sinnvoll, einen Server (im Allgemeinen mit TorchServe oder TFSering) zu erstellen, um Anfragen zu erstellen und den Funktionsanruf durch eine Postanforderung an den Server zu ersetzen.
ServerHandler erstellt einen synchronen Server und ersetzt alle Aufrufe der Funktion während der Laufzeit automatisch.
Anfragen werden an 1 Instanz eines Prozesses gestellt, auf dem ein http.server.httpserver ausgeführt wird, der die Funktion darin ausführt.
AsyncServerHandler ist ebenfalls verfügbar, was die Anforderungen asynchron macht.
Sogar Anrufe aus verschiedenen Prozessen, Threads, Multiprocessings, Flask, Fastapi und Async Event -Schleifen werden in denselben Serverprozess erfolgen.
Im Allgemeinen:
some code with a callable
kann durch eine Instanz von ServerHandler oder AsyncserverHandler ersetzt werden, die den Code als Zeichenfolge in seinem ersten Argument und den Namen des Anrufs als zweites Argument akzeptiert.
from auto_function_serving . ServerHandler import ServerHandler
callable_name = ServerHandler ( """
some independent code with a callable
""" , "callable_name" )Beispiel :
import module1
import module2
def functionname ( someinput ):
a = module1 . function1 ( someinput )
return module2 . function2 ( a )kann durch ersetzt werden durch
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" )Dekorateure ( @Asyncserverhandler.Decorator und @serverhandler.Decorator) und asyncserverhandler -Details in mehr Nutzung.
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 )) läuft http.server.httpServer.
Serverhandler- und AsyncServerHandler -Objekte können mit Gurke geladen und entladen werden.
Verwendet Popen oder Multiprocessing, um den Server auszuführen.
Verwendet nur eine einzige externe Abhängigkeit (AIOHTTP) und nur für Async.
http, nicht https.
Wählt einen Port basierend auf Hash of Input. (sofern nicht anders angegeben)
Minimaler Codeänderungen.
Sollte mit fast allen Funktionen in fast allen CPython -Envs kompatibel sein. (Nicht sicher, wo es fehlschlagen könnte? Bitte fügen Sie ein Problem hinzu, wenn Sie eine finden.)
Speicherlecks oder Fehler (vom Server) sind äußerst unwahrscheinlich, da es sich um minimale, einzelne Thread, Einzelprozess und eine Standardkomponente von Python STDLIB handelt.
Ausnahmen verursachen 5xx -Fehler, ohne den Server zu schließen.
Auch separate Prozesse stellen Anforderungen an eine Instanz desselben Servers durch, sofern nicht anders angegeben. (Weil es nach einem Server auf einem bestimmten Port sucht.).
Kann ansonsten durch festlegen, indem der Port auf einen beliebigen kostenlosen Port festgelegt wird, damit ein neues ServerHandler -Objekt einen neuen Server startet.
HTTP -Postanfragen: Leicht, nur wenige MS -Overheads, zuverlässig.
Async ist ein gutes Merkmal.
jetzt mit Tests.
Eine Codezeichenfolge als Argument für eine Klasse ist nicht pythonisch, es sei denn, der Dekorateur wird verwendet.
Das Importieren von Funktionen ist nicht ideal, selbst wenn der Dekorateur verwendet wird.
HTTP -Postanfragen: Unsicher, nur wenige MS -Overheads.
Ausnahmen auf dem Server werden nicht zurückgesandt.
Keine Charge.
Keine eingebaute Protokollierung. (Könnte hinzugefügt werden). Initialisierungsverzögerung von bis zu wenigen Sekunden, um den Server zu starten. Async -Funktionen funktionieren nicht auf dem Server.
Kein Auto -Server -Neustart im Fall Server schließt.
Kann einige Ressourcen für eine Weile (<1 min) gesperrt lassen, wenn sie nicht ordnungsgemäß geschlossen sind.
Es können Probleme auftreten, wenn Popen oder Multiprozessing nicht verfügbar sind.
Mögliche verschachtelte asynchronisierte Fehler mit Jupyter oder anderen? Bitte untersuchen Sie Nest-Asyncio und die Probleme.
Warnungen von etwas hackigen (aber legitim und völlig funktionalen) Problemumgehungen.
Schließen des Serverprozesses in Del und Atexit.Redister ( DEL ) fällt aus irgendeinem Grund aus (getestet und unwahrscheinlich).
Verwenden Sie das Paket -Manager -PIP, um auto_function_sering zu installieren
pip install auto_function_serving Der Code für den Server wird in serverHandler.base_code gespeichert, und es wird einige String -Formatierung verwendet, um die Lücken auszufüllen.
Der Serverprozess wird mit Popen (oder multiprozessieren, falls angegeben). Das erste, was es tut, ist Socket zu importieren und den Port zu binden - wenn er nicht verfügbar ist, wird der Code nach einer Ausnahme gestoppt. Daher wird nur 1 Instanz des Servers gleichzeitig auf einer Maschine ausgeführt.
Wir wissen, dass die Funktion fertig ist, nachdem wir eine gültige Get -Anfrage vom Server erhalten können.
Eingänge und Ausgänge werden als Bytes gesendet, die mit einem Gurke zu und von Objekten konvertiert werden.
Wenn der Port während der Initialisierung (Standard) keine beträgt, wird ein Port von 50000 bis 60000 ausgewählt, indem der Eingabescode unabhängig von der Quelle einer Funktion wird. Kollisionen verschiedener Funktionen sind möglich, aber unwahrscheinlich. Die Kollision derselben Funktion in mehreren Prozessen wird verwendet, um sicherzustellen, dass nur 1 Serverprozess gleichzeitig ausgeführt wird. Der Port kann bei Bedarf angegeben werden.
Overhead für kleine Ein- und Ausgabe (wenige Bytes) -
~ 2 ms für Anfragen mit urllib.request
~ 4 ms für asynchronische Anfragen mit AIOHTTP.ClientSession
Overhead für große Eingang und Ausgabe
~ 10 ms für 0,5 MB Eingang und Ausgang (1 MB Gesamtübertragung).
~ 60 ms für 5 MB Eingang und Ausgang (10 MB Gesamtübertragung).
~ 600 ms für 50 MB Eingang und Ausgang (100 MB Gesamtübertragung).
Es kann auch mit dem bereitgestellten Dekorator für Funktionen ohne Abhängigkeiten außerhalb der Funktion verwendet werden.
from auto_function_serving . ServerHandler import ServerHandler
@ ServerHandler . decorator
def someheavyfunction ( args , ** kwargs ):
for i in range ( big_number )
someexpensivecomputationImporte innerhalb der Funktion funktionieren
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 )
... etcWenn das Somemodul keine teure globale Belastung hat.
from auto_function_serving . ServerHandler import ServerHandler
from somemodule import someheavyfunction
someheavyfunction = ServerHandler . decorator ( someheavyfunction )Die IP -Adresse kann durch Einstellen von serverHandler.ip_address (Standard "127.0.0.1") geändert werden, bevor eine neue Instanz erstellt wird.
AsyncServerHandler ist ebenfalls verfügbar, das AIOHTTP verwendet, um die Anforderungen asynchron zu stellen, um mit Fastapi und anderen ASync -Anwendungsfällen zu verwenden.
AsyncServerHandler hat die gleiche Verwendung wie ServerHandler, außer dass Anrufe erwartet oder mit asyncio.run () oder mit asyncio.get_event_loop () run_until_complete () erwartet oder verwendet werden müssen.
Die Anzahl der asynchronisierten Aufrufe kann begrenzt werden, indem asyncserverhandler.tcpconnector_limit festgelegt wird, die die TCPConnector -Grenze steuert (Standard 100). Die Verwendung von Semaphor ist auch etwas zu beachten.
Bibliotheken: Sellerie, Tfsering, Torchserve, Flask
Senden von Globalen und Einheimischen an Exec
Ast Bäume
Pull -Anfragen sind willkommen.
Apache -Lizenz 2.0