diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 533a5c90fe..06f471120b 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -2,16 +2,10 @@
-
-
-
-
-
+
-
-
-
+
@@ -92,13 +86,13 @@
-
+
-
+
@@ -168,11 +162,11 @@
-
+
-
-
+
+
@@ -180,16 +174,17 @@
-
+
-
-
+
+
-
-
-
+
+
+
+
@@ -286,8 +281,8 @@
-
+
@@ -507,28 +502,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Test Notebook.ipynb b/Test Notebook.ipynb
index 165f9bd500..6a519489c5 100644
--- a/Test Notebook.ipynb
+++ b/Test Notebook.ipynb
@@ -2,15 +2,14 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
- "name": "stdout",
+ "name": "stderr",
"output_type": "stream",
"text": [
- "The autoreload extension is already loaded. To reload it, use:\n",
- " %reload_ext autoreload\n"
+ "Using TensorFlow backend.\n"
]
}
],
@@ -26,68 +25,23 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "C:\\Users\\islam\\Anaconda3\\envs\\tensorflow\\lib\\site-packages\\keras\\engine\\saving.py:327: UserWarning: Error in loading the saved optimizer state. As a result, your model is starting with a freshly initialized optimizer.\n",
- " warnings.warn('Error in loading the saved optimizer '\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"model = load_model('.models/mnist-cnn.h5')"
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "http://localhost:6002/templates/tmp_html.html\n"
- ]
- },
- {
- "ename": "OSError",
- "evalue": "[Errno 10048] error while attempting to bind on address ('127.0.0.1', 5680): only one usage of each socket address (protocol/network address/port) is normally permitted",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mOSError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mcreate_server\u001b[1;34m(self, protocol_factory, host, port, family, flags, sock, backlog, ssl, reuse_address, reuse_port)\u001b[0m\n\u001b[0;32m 1050\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1051\u001b[1;33m \u001b[0msock\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msa\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1052\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mOSError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;31mOSError\u001b[0m: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted",
- "\nDuring handling of the above exception, another exception occurred:\n",
- "\u001b[1;31mOSError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0miface\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgradio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mInterface\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0minput\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'sketchpad'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0moutput\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'class'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mmodel_obj\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmodel_type\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'keras'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0miface\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlaunch\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;32m~\\Repos\\gradio\\gradio.py\u001b[0m in \u001b[0;36mlaunch\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 244\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 245\u001b[0m \u001b[0mstart_server\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mwebsockets\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mserve\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcommunicate\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mLOCALHOST_IP\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mSOCKET_PORT\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 246\u001b[1;33m \u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_event_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_until_complete\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstart_server\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 247\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 248\u001b[0m \u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_event_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_forever\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\site-packages\\nest_asyncio.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[1;34m(self, future)\u001b[0m\n\u001b[0;32m 57\u001b[0m \u001b[1;32mwhile\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdone\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 58\u001b[0m \u001b[0mrun_once\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 59\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 60\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 61\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_run_until_complete_orig\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfuture\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\asyncio\\tasks.py\u001b[0m in \u001b[0;36m_step\u001b[1;34m(***failed resolving arguments***)\u001b[0m\n\u001b[0;32m 178\u001b[0m \u001b[1;31m# We use the `send` method directly, because coroutines\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 179\u001b[0m \u001b[1;31m# don't have `__iter__` and `__next__` methods.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 180\u001b[1;33m \u001b[0mresult\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 181\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 182\u001b[0m \u001b[0mresult\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mthrow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mexc\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\asyncio\\tasks.py\u001b[0m in \u001b[0;36m_wrap_awaitable\u001b[1;34m(awaitable)\u001b[0m\n\u001b[0;32m 535\u001b[0m \u001b[0mthat\u001b[0m \u001b[0mwill\u001b[0m \u001b[0mlater\u001b[0m \u001b[0mbe\u001b[0m \u001b[0mwrapped\u001b[0m \u001b[1;32min\u001b[0m \u001b[0ma\u001b[0m \u001b[0mTask\u001b[0m \u001b[0mby\u001b[0m \u001b[0mensure_future\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 536\u001b[0m \"\"\"\n\u001b[1;32m--> 537\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;32myield\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mawaitable\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__await__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 538\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 539\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\site-packages\\websockets\\py35\\server.py\u001b[0m in \u001b[0;36m__await_impl__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[1;31m# Duplicated with __iter__ because Python 3.7 requires an async function\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[1;31m# (as explained in __await__ below) which Python 3.4 doesn't support.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[0mserver\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mawait\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_creating_server\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 14\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mws_server\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwrap\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mws_server\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m~\\Anaconda3\\envs\\tensorflow\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mcreate_server\u001b[1;34m(self, protocol_factory, host, port, family, flags, sock, backlog, ssl, reuse_address, reuse_port)\u001b[0m\n\u001b[0;32m 1053\u001b[0m raise OSError(err.errno, 'error while attempting '\n\u001b[0;32m 1054\u001b[0m \u001b[1;34m'to bind on address %r: %s'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1055\u001b[1;33m % (sa, err.strerror.lower()))\n\u001b[0m\u001b[0;32m 1056\u001b[0m \u001b[0mcompleted\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1057\u001b[0m \u001b[1;32mfinally\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;31mOSError\u001b[0m: [Errno 10048] error while attempting to bind on address ('127.0.0.1', 5680): only one usage of each socket address (protocol/network address/port) is normally permitted"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Error in connection handler\n",
- "Traceback (most recent call last):\n",
- " File \"C:\\Users\\islam\\Anaconda3\\envs\\tensorflow\\lib\\site-packages\\websockets\\server.py\", line 169, in handler\n",
- " yield from self.ws_handler(self, path)\n",
- " File \"C:\\Users\\islam\\Repos\\gradio\\gradio.py\", line 231, in communicate\n",
- " processed_output = self.output_interface._post_process(prediction)\n",
- " File \"C:\\Users\\islam\\Repos\\gradio\\gradio.py\", line 165, in _post_process\n",
- " return emotion_dict[prediction]\n",
- "KeyError: 7\n"
+ "Model publicly available for 8 hours at: https://57d2bd20.ngrok.io/templates/tmp_html.html\n"
]
}
],
diff --git a/gradio.py b/gradio.py
index 4c28eba925..2635284c03 100644
--- a/gradio.py
+++ b/gradio.py
@@ -165,7 +165,6 @@ class Interface():
else:
raise ValueError('model_type must be one of: "sklearn" or "keras" or "func".')
-
async def communicate(self, websocket, path):
"""
Method that defines how this interface communicates with the websocket.
@@ -173,27 +172,31 @@ class Interface():
:param path: ignored
"""
while True:
- processed_input = self.input_interface._pre_process(await websocket.recv())
- prediction = self.predict(processed_input)
- processed_output = self.output_interface._post_process(prediction)
- await websocket.send(str(processed_output))
+ try:
+ msg = await websocket.recv()
+ processed_input = self.input_interface._pre_process(msg)
+ prediction = self.predict(processed_input)
+ processed_output = self.output_interface._post_process(prediction)
+ await websocket.send(str(processed_output))
+ except websockets.exceptions.ConnectionClosed:
+ pass
def launch(self, share_link=True):
"""
Standard method shared by interfaces that launches a websocket at a specified IP address.
"""
- path_to_server = networking.start_simple_server()
+ server_port = networking.start_simple_server()
+ path_to_server = 'http://localhost:{}/'.format(server_port)
path_to_template = self._build_template()
- chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s' # TODO(abidlabs): remove
-
- print(path_to_server + path_to_template)
- webbrowser.get(chrome_path).open(path_to_server + path_to_template) # TODO(abidlabs): fix this
+ chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s' # TODO(abidlabs): try otherwise general
+ webbrowser.get(chrome_path).open(path_to_server + path_to_template)
start_server = websockets.serve(self.communicate, LOCALHOST_IP, SOCKET_PORT)
+ print("Model available locally at: {}".format(path_to_server))
if share_link:
- ngrok_url = networking.setup_ngrok()
- print("Model accessiable for 8 hours at: {}".format(ngrok_url))
+ ngrok_url = networking.setup_ngrok(server_port)
+ print("Model available publicly for 8 hours at: {}".format(ngrok_url + '/' + path_to_template))
asyncio.get_event_loop().run_until_complete(start_server)
try:
diff --git a/networking.py b/networking.py
index 2654991b0c..edae92e4de 100644
--- a/networking.py
+++ b/networking.py
@@ -3,8 +3,11 @@ import requests
import zipfile
import io
import sys
+import os
-INITIAL_PORT_VALUE = '6002'
+INITIAL_PORT_VALUE = 6002
+LOCALHOST_PREFIX = 'localhost:'
+NGROK_TUNNELS_URL = "http://localhost:4040/api/tunnels"
NGROK_ZIP_URLS = {
"linux": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip",
"darwin": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip",
@@ -12,8 +15,9 @@ NGROK_ZIP_URLS = {
}
def start_simple_server():
- subprocess.Popen(['python', '-m', 'http.server', INITIAL_PORT_VALUE])
- return 'http://localhost:{}/'.format(INITIAL_PORT_VALUE)
+ subprocess.Popen(['python', '-m', 'http.server', str(INITIAL_PORT_VALUE)])
+ return INITIAL_PORT_VALUE
+
def download_ngrok():
try:
@@ -24,7 +28,17 @@ def download_ngrok():
r = requests.get(zip_file_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
- z.extractall("gradio/")
+ z.extractall()
def setup_ngrok(local_port):
+ if not(os.path.isfile('ngrok.exe')):
+ download_ngrok()
+ subprocess.Popen(['ngrok', 'http', str(local_port)])
+ r = requests.get(NGROK_TUNNELS_URL)
+ for tunnel in r.json()['tunnels']:
+ if LOCALHOST_PREFIX + str(local_port) in tunnel['config']['addr']:
+ return tunnel['public_url']
+ raise RuntimeError("Not able to retrieve ngrok public URL")
+
+