From 97e118efdb05bdb2efd6269522c25177860b5bb4 Mon Sep 17 00:00:00 2001 From: leonwanghui Date: Fri, 9 Apr 2021 10:13:48 +0800 Subject: [PATCH] Fix some bugs when serving in Windows operating system Signed-off-by: leonwanghui --- requirements.txt | 1 + setup.py | 1 + tinyms/serving/__init__.py | 19 +++++++++++++- tinyms/serving/client/client.py | 22 +++++++++++++--- tinyms/serving/servable/servable.py | 6 ++--- tinyms/serving/server/server.py | 39 +++++++++++++---------------- 6 files changed, 58 insertions(+), 30 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2b767097..7e49a7c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ requests >= 2.22.0 flask >= 1.1.1 wheel >= 0.32.0 setuptools >= 40.8.0 +python-Levenshtein >= 0.10.2 gensim >= 3.8.1 diff --git a/setup.py b/setup.py index c24fb3c9..19254655 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ def _write_version(file): 'flask >= 1.1.1', 'wheel >= 0.32.0', 'setuptools >= 40.8.0', + 'python-Levenshtein >= 0.10.2', 'gensim >= 3.8.1', ] diff --git a/tinyms/serving/__init__.py b/tinyms/serving/__init__.py index b92a2f86..434cc340 100644 --- a/tinyms/serving/__init__.py +++ b/tinyms/serving/__init__.py @@ -12,7 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ -""".. TinyMS Serving package.""" +""" +.. TinyMS Serving package. + +This module refers to the process of serving pre-trained models so that +they can quickly and efficiently process data input by users and obtain +results. TinyMS provides a complete set of start server (`start_server`), +check backend (`list_servables`), check start status (`server_started`) +and shut down the server (`shutdown`) and other functions based on +[Flask](https://flask.palletsprojects.com/en/1.1.x/). + +Examples: + >>> from tinyms.serving import start_server, server_started, list_servables, predict + >>> + >>> start_server() + >>> if server_started(): + ... print(list_servables()) + ... predict('example.jpg', 'servable_name', dataset_name='mnist') +""" from . import client, server from .client import * from .server import * diff --git a/tinyms/serving/client/client.py b/tinyms/serving/client/client.py index 412ad7f1..7e97b3cb 100644 --- a/tinyms/serving/client/client.py +++ b/tinyms/serving/client/client.py @@ -47,8 +47,10 @@ def server_started(host='127.0.0.1', port=5000): Examples: >>> # Running the quickstart tutorial, after starting the server + >>> from tinyms.serving import server_started, predict + >>> >>> if server_started() is True: - >>> print(predict(image_path, 'lenet5', 'mnist', strategy)) + ... print(predict(image_path, 'lenet5', 'mnist', strategy)) """ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: @@ -63,8 +65,8 @@ def list_servables(): """ List the model that is currently served by the backend server. - A `GET` request will be sent to the server(127.0.0.1:5000) which will then - be routed to 127.0.0.1:5000/servables, and the backend servalbe information + A `GET` request will be sent to the server(127.0.0.1:5000) which will then + be routed to 127.0.0.1:5000/servables, and the backend servable information will be returned to the client. Returns: @@ -74,8 +76,18 @@ def list_servables(): Examples: >>> # Running the quickstart tutorial, after server started and servable json defined + >>> from tinyms.serving import list_servables + >>> >>> list_servables() - [{'description': 'This servable hosts a lenet5 model predicting numbers', 'model': {'class_num': 10, 'format': 'ckpt', 'name': 'lenet5'}, 'name': 'lenet5'}] + [{ + 'description': 'This servable hosts a lenet5 model predicting numbers', + 'model': { + 'class_num': 10, + 'format': 'ckpt', + 'name': 'lenet5' + }, + 'name': 'lenet5' + }] """ headers = {'Content-Type': 'application/json'} @@ -112,6 +124,8 @@ def predict(img_path, servable_name, dataset_name="mnist", strategy="TOP1_CLASS" Examples: >>> # Running the quickstart tutorial, after server started and servable json defined + >>> from tinyms.serving import predict + >>> >>> print(predict('/root/7.png', 'lenet5', 'mnist', 'TOP1_CLASS')) TOP1: 7, score: 0.99943381547927856445 """ diff --git a/tinyms/serving/servable/servable.py b/tinyms/serving/servable/servable.py index 79b2cfeb..ff4d22dd 100644 --- a/tinyms/serving/servable/servable.py +++ b/tinyms/serving/servable/servable.py @@ -43,7 +43,7 @@ def servable_search(name=None): A string of servable values will be returned if servable json exists, otherwise error message. Examples: - >>> # In the server part, before running the predict function, servable_serch is called to check and get the result. + >>> # In the server part, before running the predict function, servable_search is called to check and get the result. >>> res = servable_search(servable_name) >>> servable = res['servables'][0] >>> res = predict(instance, servable_name, servable['model'], strategy) @@ -81,7 +81,7 @@ def predict(instance, servable_name, servable_model, strategy): A network will be constructed based on the input and servable data, then load the checkpoint and do the predict. Args: - instance (dict): the dict of input image after transformation, with keys of `shape`, `dtype` and `data`(Image object). + instance (dict): the dict of input image after transformation, with keys of `shape`, `dtype` and `data`(Image object). servable_name (str): servable name servable_model (str): name of the model strategy (str): output strategy, usually select between `TOP1_CLASS` and `TOP5_CLASS`, for cyclegan, select between `gray2color` and `color2gray` @@ -90,7 +90,7 @@ def predict(instance, servable_name, servable_model, strategy): The dict object of predicted result after post process. Examples: - >>> # In the server part, after servavle_search + >>> # In the server part, after servable_search >>> res = predict(instance, servable_name, servable['model'], strategy) >>> return jsonify(res) """ diff --git a/tinyms/serving/server/server.py b/tinyms/serving/server/server.py index 676c7a73..14029b9e 100644 --- a/tinyms/serving/server/server.py +++ b/tinyms/serving/server/server.py @@ -37,7 +37,7 @@ def predict_server(): A json object of predicted result will be sent back to the client. Examples: - >>> # In the client part, the request will be routed and processed here + >>> # In the client part, the request will be routed and processed here >>> url = "http://127.0.0.1:5000/predict" >>> res = requests.post(url=url, headers=headers, data=json.dumps(payload)) """ @@ -69,7 +69,7 @@ def list_servables(): A json object of servable information in the backend will be sent back to the client. Examples: - >>> # In the client part, the servable search request will be routed and processed here + >>> # In the client part, the servable search request will be routed and processed here >>> res = requests.get(url=url, headers=headers) >>> res_body = res.json() """ @@ -120,20 +120,18 @@ def shutdown(self): return 'No server detected' def windows_run_server(self): - cmd = 'python -c "from run_flask import run_flask; run_flask()"' + cmd = 'python -c "from tinyms.serving import run_flask; run_flask()"' server_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) - + for sig in [signal.SIGINT, signal.SIGTERM]: signal.signal(sig, self.signal_handler) def linux_run_server(self): cmd = ['python -c "from tinyms.serving import run_flask; run_flask()"'] server_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) - - # 我发现此处并未设置一个循环等候信号的逻辑,这会导致服务使用ctrl+c无法正常关闭整个服务,我不明白当初的设计思路,此处可选 - while True: - for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]: - signal.signal(sig, self.signal_handler) + + for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]: + signal.signal(sig, self.signal_handler) def run(self): if self.system_name == "windows": @@ -156,7 +154,7 @@ def run_flask(host='127.0.0.1', port=5000): Server Started Examples: - >>> # In the start_server function + >>> # In the start_server function >>> cmd = ['python -c "from tinyms.serving import run_flask; run_flask()"'] >>> server_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) """ @@ -180,37 +178,34 @@ def start_server(host='127.0.0.1', port=5000): Start the server in a sub process. Examples: - >>> # In the client part + >>> # In the client part + >>> from tinyms.serving import start_server + >>> >>> start_server() Server starts at host 127.0.0.1, port 5000 """ if server_started() is True: - print('Server already started at host %s, port %d'%(host, port)) + print('Server already started at host %s, port %d' % (host, port)) else: server = FlaskServer() server.run() - print('Server starts at host %s, port %d' %(host, port)) - - def signal_handler(signal, frame): - shutdown() - sys.exit(0) - - # for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]: - # signal.signal(sig, signal_handler) + print('Server starts at host %s, port %d' % (host, port)) def shutdown(): """ Shutdown the flask server. - Search fot the pid of the process running on port 5000, and kill it. This function will be automatically called when SIGINT, SIGHUP and SIGTERM signals catched. + Search fot the pid of the process running on port 5000, and kill it. This function will be automatically called when SIGINT, SIGHUP and SIGTERM signals caught. Returns: A string message of server shutting down or not. Examples: - >>> # In the client part, after predict() + >>> # In the client part, after calling predict() + >>> from tinyms.serving import shutdown + >>> >>> shutdown() 'Server shutting down...' """