Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some bugs when serving in Windows operating system #74

Merged
merged 1 commit into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
]

Expand Down
19 changes: 18 additions & 1 deletion tinyms/serving/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
22 changes: 18 additions & 4 deletions tinyms/serving/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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'}
Expand Down Expand Up @@ -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
"""
Expand Down
6 changes: 3 additions & 3 deletions tinyms/serving/servable/servable.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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`
Expand All @@ -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)
"""
Expand Down
39 changes: 17 additions & 22 deletions tinyms/serving/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
"""
Expand Down Expand Up @@ -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()
"""
Expand Down Expand Up @@ -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":
Expand All @@ -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)
"""
Expand All @@ -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...'
"""
Expand Down