mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-24 10:54:04 +08:00
updated threading so that concurrency issues are resolved and killing the main thread kills the others
This commit is contained in:
parent
077b663d2a
commit
ca2d44319d
@ -1,26 +1,5 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ModuleNotFoundError",
|
||||
"evalue": "No module named 'torchvision'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[1;32m<ipython-input-5-82bc70f8d29b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mtorchvision\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodels\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mmodels\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'torchvision'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torchvision.models as models\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
@ -30,6 +9,7 @@
|
||||
"%load_ext autoreload\n",
|
||||
"%autoreload 2\n",
|
||||
"\n",
|
||||
"import numpy as np\n",
|
||||
"import tensorflow as tf\n",
|
||||
"import gradio"
|
||||
]
|
||||
@ -40,7 +20,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = tf.keras.applications.inception_v3.InceptionV3()"
|
||||
"# model = tf.keras.applications.inception_v3.InceptionV3()"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -50,12 +30,17 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"inp = gradio.inputs.ImageUpload(image_width=299, image_height=299)\n",
|
||||
"out = gradio.outputs.Label(label_names='imagenet1000', max_label_length=8, num_top_classes=5)\n",
|
||||
"out = gradio.outputs.Label(label_names='imagenet1000', max_label_length=8, num_top_classes=8)\n",
|
||||
"\n",
|
||||
"iface = gradio.Interface(inputs=inp, \n",
|
||||
" outputs=out,\n",
|
||||
" model=model, \n",
|
||||
" model_type='keras')"
|
||||
" model=lambda x: np.array(1), \n",
|
||||
" model_type='function')\n",
|
||||
"\n",
|
||||
"# iface = gradio.Interface(inputs=inp, \n",
|
||||
"# outputs=out,\n",
|
||||
"# model=model, \n",
|
||||
"# model_type='keras')"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -70,8 +55,8 @@
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"NOTE: Gradio is in beta stage, please report all bugs to: a12d@stanford.edu\n",
|
||||
"Model is running locally at: http://localhost:7861/interface.html\n",
|
||||
"Model available publicly for 8 hours at: http://f0cf4515.ngrok.io/interface.html\n"
|
||||
"Model is running locally at: http://localhost:7860/interface.html\n",
|
||||
"To create a public link, set `share=True` in the argument to `launch()`\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -81,52 +66,22 @@
|
||||
" <iframe\n",
|
||||
" width=\"1000\"\n",
|
||||
" height=\"500\"\n",
|
||||
" src=\"http://localhost:7861/interface.html\"\n",
|
||||
" src=\"http://localhost:7860/interface.html\"\n",
|
||||
" frameborder=\"0\"\n",
|
||||
" allowfullscreen\n",
|
||||
" ></iframe>\n",
|
||||
" "
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.lib.display.IFrame at 0x1f4f871aa90>"
|
||||
"<IPython.lib.display.IFrame at 0x26c5900fba8>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /interface.html HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /interface.html HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/css/style.css HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/js/utils.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:05] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:06] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:06] \"GET /static/img/logo_inline.png HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:06] code 404, message File not found\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:06] \"GET /favicon.ico HTTP/1.1\" 404 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:27] \"GET /interface.html HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 12:46:27] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /interface.html HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/css/style.css HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/js/utils.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/img/logo_inline.png HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:34] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:35] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:35] code 404, message File not found\n",
|
||||
"127.0.0.1 - - [07/Mar/2019 13:02:35] \"GET /favicon.ico HTTP/1.1\" 404 -\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"iface.launch(inline=True, browser=True, share=True);"
|
||||
"iface.launch(inline=True, browser=False, share=False);"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -1,6 +1,8 @@
|
||||
from argparse import ArgumentParser
|
||||
import gradio
|
||||
import numpy as np
|
||||
import signal
|
||||
import time
|
||||
|
||||
parser = ArgumentParser(description='Arguments for Building Interface')
|
||||
parser.add_argument('-i', '--inputs', type=str, help="name of input interface")
|
||||
@ -14,13 +16,29 @@ args = parser.parse_args()
|
||||
|
||||
def launch_interface(args):
|
||||
io = gradio.Interface(inputs=args.inputs, outputs=args.outputs, model=lambda x:np.array(1), model_type='function')
|
||||
io.launch(share=args.share)
|
||||
# input_interface = gradio.inputs.registry[args.inputs.lower()]()
|
||||
# output_interface = gradio.outputs.registry[args.outputs.lower()]()
|
||||
# temp_dir = tempfile.mkdtemp()
|
||||
# gradio.networking.build_template(temp_dir, input_interface, output_interface)
|
||||
# print('Open this path in your browser to access the input interface: {}'.format(
|
||||
# os.path.join(temp_dir, INDEX_FILE_NAME)))
|
||||
httpd, _, _ = io.launch(share=args.share)
|
||||
|
||||
class ServiceExit(Exception):
|
||||
"""
|
||||
Custom exception which is used to trigger the clean exit
|
||||
of all running threads and the main program.
|
||||
"""
|
||||
pass
|
||||
|
||||
def service_shutdown(signum, frame):
|
||||
print('Shutting server down due to signal %d' % signum)
|
||||
httpd.shutdown()
|
||||
raise ServiceExit
|
||||
|
||||
signal.signal(signal.SIGTERM, service_shutdown)
|
||||
signal.signal(signal.SIGINT, service_shutdown)
|
||||
|
||||
try:
|
||||
# Keep the main thread running, otherwise signals are ignored.
|
||||
while True:
|
||||
time.sleep(0.5)
|
||||
except ServiceExit:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -59,7 +59,7 @@ class Sketchpad(AbstractInput):
|
||||
image_encoded = content.split(',')[1]
|
||||
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
|
||||
im = preprocessing_utils.resize_and_crop(im, (self.image_width, self.image_height))
|
||||
array = np.array(im).flatten().reshape(1, self.image_width, self.image_height, 1)
|
||||
array = np.array(im).flatten().reshape(1, self.image_width, self.image_height)
|
||||
return array
|
||||
|
||||
|
||||
|
@ -11,6 +11,7 @@ import gradio.inputs
|
||||
import gradio.outputs
|
||||
from gradio import networking
|
||||
import tempfile
|
||||
import threading
|
||||
|
||||
nest_asyncio.apply()
|
||||
|
||||
@ -140,7 +141,7 @@ class Interface:
|
||||
output_directory = tempfile.mkdtemp()
|
||||
|
||||
# Set up a port to serve the directory containing the static files with interface.
|
||||
server_port = networking.start_simple_server(output_directory)
|
||||
server_port, httpd = networking.start_simple_server(output_directory)
|
||||
path_to_server = 'http://localhost:{}/'.format(server_port)
|
||||
networking.build_template(output_directory, self.input_interface, self.output_interface)
|
||||
|
||||
@ -170,9 +171,10 @@ class Interface:
|
||||
# Keep the server running in the background.
|
||||
asyncio.get_event_loop().run_until_complete(start_server)
|
||||
try:
|
||||
asyncio.get_event_loop().run_forever()
|
||||
except RuntimeError: # Runtime errors are thrown in jupyter notebooks because of async.
|
||||
pass
|
||||
_ = get_ipython()
|
||||
except NameError: # Runtime errors are thrown in jupyter notebooks because of async.
|
||||
t = threading.Thread(target=asyncio.get_event_loop().run_forever, daemon=True)
|
||||
t.start()
|
||||
|
||||
if inline is None:
|
||||
try: # Check if running interactively using ipython.
|
||||
@ -193,4 +195,4 @@ class Interface:
|
||||
from IPython.display import IFrame
|
||||
display(IFrame(path_to_server + networking.TEMPLATE_TEMP, width=1000, height=500))
|
||||
|
||||
return path_to_server + networking.TEMPLATE_TEMP, site_ngrok_url
|
||||
return httpd, path_to_server + networking.TEMPLATE_TEMP, site_ngrok_url
|
@ -147,6 +147,9 @@ def serve_files_in_background(port, directory_to_serve=None):
|
||||
fullpath = os.path.join(self.server.base_path, relpath)
|
||||
return fullpath
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
class HTTPServer(BaseHTTPServer):
|
||||
"""The main server, you pass in base_path which is the path you want to serve requests from"""
|
||||
|
||||
@ -154,25 +157,28 @@ def serve_files_in_background(port, directory_to_serve=None):
|
||||
self.base_path = base_path
|
||||
BaseHTTPServer.__init__(self, server_address, RequestHandlerClass)
|
||||
|
||||
|
||||
httpd = HTTPServer(directory_to_serve, (LOCALHOST_NAME, port))
|
||||
|
||||
# Now loop forever
|
||||
def serve_forever():
|
||||
try:
|
||||
while True:
|
||||
sys.stdout.flush()
|
||||
# sys.stdout.flush()
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
httpd.server_close()
|
||||
|
||||
thread = threading.Thread(target=serve_forever)
|
||||
thread = threading.Thread(target=serve_forever, daemon=True)
|
||||
thread.start()
|
||||
|
||||
return httpd
|
||||
|
||||
|
||||
def start_simple_server(directory_to_serve=None):
|
||||
port = get_first_available_port(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS)
|
||||
serve_files_in_background(port, directory_to_serve)
|
||||
return port
|
||||
httpd = serve_files_in_background(port, directory_to_serve)
|
||||
return port, httpd
|
||||
|
||||
|
||||
def download_ngrok():
|
||||
|
Loading…
Reference in New Issue
Block a user