I have a Flask App and a Tensorboad server. Is there a way by which I can map the Tensorboard server to one of the endpoints of Flask so that as soon as I hit that endpoint it triggers the Tensorboard server?
Flask application
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/hello-world', methods=['GET', 'POST'])
def say_hello():
return jsonify({'result': 'Hello world'})
if __name__ == "__main__":
app.run(host=host, port=5000)
Tensorboard server code:
from tensorboard.program import TensorBoard, setup_environment
def tensorboard_main(host, port, logdir):
configuration = list([""])
configuration.extend(["--host", host])
configuration.extend(["--port", port])
configuration.extend(["--logdir", logdir])
tensorboard = TensorBoard()
tensorboard.configure(configuration)
tensorboard.main()
if __name__ == "__main__":
host = "0.0.0.0"
port = "7070"
logdir = '/tmp/logdir'
tensorboard_main(host, port, logdir)
I tried creating an endpoint in Flask app and then added tensorboard_main(host, port, logdir) in the hope that if I hit the endpoint then the server will start but I got no luck.
I found out that to integrate a TensorBoard server into a larger Flask app, the best way would be to compose the applications at the WSGI level.
The tensorboard.program API allows us to pass a custom server
class. The signature here is that server_class should be a callable which takes the TensorBoard WSGI app and returns a server that satisfies the TensorBoardServer interface.
Hence the code is:
import os
import flask
import tensorboard as tb
from werkzeug import serving
from werkzeug.middleware import dispatcher
HOST = "0.0.0.0"
PORT = 7070
flask_app = flask.Flask(__name__)
#flask_app.route("/hello-world", methods=["GET", "POST"])
def say_hello():
return flask.jsonify({"result": "Hello world"})
class CustomServer(tb.program.TensorBoardServer):
def __init__(self, tensorboard_app, flags):
del flags # unused
self._app = dispatcher.DispatcherMiddleware(
flask_app, {"/tensorboard": tensorboard_app}
)
def serve_forever(self):
serving.run_simple(HOST, PORT, self._app)
def get_url(self):
return "http://%s:%s" % (HOST, PORT)
def print_serving_message(self):
pass # Werkzeug's `serving.run_simple` handles this
def main():
program = tb.program.TensorBoard(server_class=CustomServer)
program.configure(logdir=os.path.expanduser("~/tensorboard_data"))
program.main()
if __name__ == "__main__":
main()
You can use multiprocessing here: create one process for flask and another for tensorboard, then run it on the same host.
Code:
from multiprocessing import Process
from tensorboard.program import TensorBoard
from flask import Flask, jsonify
app = Flask(__name__)
def tensorboard_main(host, port, logdir):
configuration = list([""])
configuration.extend(["--host", host])
configuration.extend(["--port", port])
configuration.extend(["--logdir", logdir])
tensorboard = TensorBoard()
tensorboard.configure(configuration)
tensorboard.main()
def flask_main(app, host, port):
return app.run(host=host, port=port)
#app.route("/hello-world", methods=["GET", "POST"])
def say_hello():
return jsonify({"result": "Hello world"})
if __name__ == "__main__":
host = "0.0.0.0"
port_for_tensorboard = "7070"
port_for_flask = "5000"
logdir = "/tmp/logdir"
process_for_tensorboard = Process(target=tensorboard_main, args=(host, port_for_tensorboard, logdir))
process_for_flask = Process(target=flask_main, args=(app, host, port_for_flask))
process_for_tensorboard.start()
process_for_flask.start()
process_for_tensorboard.join()
process_for_flask.join()
If you want that inside flask endpoint tensorboard will be show some things, then you need to look at shared data from one process to another (think it would be more complicated than this example)
Related
I am trying to run a flask server from another module and then close the server (it's not the main point of the application), currently the code looks like this for webserver.py
from flask import Flask, render_template
from flask_classful import FlaskView
import os
from werkzeug.utils import secure_filename
from flask import request
host = 'localhost'
debug = True
app = Flask (__name__)
app.config
#app.route('/')
def main():
return render_template("index.html")
def run():
if __name__ == 'Refactor2':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
def shutdownServer():
shutdown_server()
return "Server is shutting down"
I am then trying to run this in the following module (named Refactor2):
import webserver
class buyer:
def __init__(self, email, password):
self.email = email
self.password = password
def server_run(self):
run()
print("Server has been started")
However, the server does not run and I cannot navigate to the webpage. There are no error messages shown.
Seems like an unusual way to launch a Flask app, but with that aside...
Assuming you're running this with python Refactor2.py, __name__ will be 'webserver'.
This can be demonstrated with a minimal example:
$ cat webserver.py
def run():
print (__name__)
$ cat Refactor2.py
import webserver
webserver.run()
$ python Refactor2.py
webserver
So in your webserver module you could do do:
def run():
if __name__ == 'webserver':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
Or just:
def run():
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
And call it like:
import webserver
# ...
class buyer:
# ...
def server_run(self):
webserver.run()
print("Server has been started")
Of course, that 'Server has been started' won't actually be reached until the server (the webserver.run call) has completed and the server has stopped.
Again, this seems like an odd way to launch an application. I suggest you investigate the docs on how to run Flask in production, as it seems what you're trying to acheive is the job of an orchestration system, and not the python process itself. In a production env, you should use a WSGI server like gunicorn, instead of the dev server (app.run). Granted, perhaps you know this already ;)
__name__ gives the name of the current module. So in your run() method __name__ is probably resolving to webserver. I'd suggest passing the name as a variable to run() from server_run()
webserver.py
def run(name):
if name == 'Refactor2':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
Refactor2
import webserver
class buyer:
def __init__(self, email, password):
self.email = email
self.password = password
def server_run(self):
run(__name__)
print("Server has been started")
Note that if Refactor2 is in a package you might get a dotted module name, like 'src.Refactor2'. It might be better to pass a more explicit name to run, as if you rename Refactor2 you'll need to update your hardcode in webserver.py too. Something like
def server_run(self):
webserver.run('buyer')
print("Server has been started")
and
(webserver.py)
def run(name):
if name == 'buyer':
app.run(ssl_context = (r"path_to_cert", r"path_to_key"), host = "localhost", port = 443)
edit: not sure if you provided a full code example, but it also looks like maybe you're not calling the right run() method in server_run() - it looks like it should be called on the webserver module, which I edited my answer to reflect
So I have a simple flask server and wanted to listen to nsqd,(My nsqd and nsqlookupd dockers are running fine.) I'm using gnsq from python as a tool to achieve that
server.py:
from flask import Flask
import gnsq
consumer = gnsq.Consumer('test_topic', 'test_channel', '0.0.0.0:4161')
#consumer.on_message.connect
def handler(consumer, message):
print ('got message:', message.body)
consumer.start()
app = Flask(__name__)
#app.route("/")
def hello():
return "Flasky"
and when I run the server all I get is
[0.0.0.0:4161] connection failed (NSQSocketError(57, 'Socket is not connected'))
I tried changing ports as well but still persist.
I'm trying to make a Flask app that uses WebSockets. The example from Flask-sockets works but how would I send a message from a regular view?
Similarly to how Flask-SocketIO use .emit() and .send()-methods.
In the example below (from the Flask-Sockets example) I would for instance like to be able to broadcast a message from the hello-view.
from flask import Flask
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
#sockets.route('/echo')
def echo_socket(ws):
while not ws.closed:
message = ws.receive()
ws.send(message)
#app.route('/')
def hello():
# How can I send a WebSocket message from here?
return 'Hello World!'
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
server.serve_forever()
You can use a global socket list of all client. Traverse all list and send message to all ws instance.
Example code;
from flask import Flask, render_template
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
ws_list = []
#sockets.route('/echo')
def echo_socket(ws):
ws_list.append(ws)
while not ws.closed:
message = ws.receive()
ws.send(message)
#app.route('/')
def hello():
# How can I send a WebSocket message from here?
return render_template('index.html')
#app.route('/send_message_to_all_client')
def broadcast():
for ws in ws_list:
if not ws.closed:
ws.send("broadcast message")
else:
# Remove ws if connection closed.
ws_list.remove(ws)
return "ok"
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
server.serve_forever()
I'm having an issue with dockers, I followed official docker tutorial to deploy a web app (and luckily a python/flask one) but when I tried to deploy my app when I come to the connection part it failed and reply "Connection was reset"
Code
import json
import threading
import thread
import io
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# Global variables
app = Flask(__name__)
lock = threading.Semaphore(0)
IOCReplay.lock = lock
async_mode = None
socketio = SocketIO(app)
IOCReplay.socketio = socketio
#app.route("/")
def root():
return render_template('index.html')
#app.route("/dependencies")
def getDependencies():
data = ''
with open('./dependencies.json') as data_file:
data = json.load(data_file)
return json.dumps(data)
if __name__ == "__main__":
socketio.run(app, port=5000)
docker run -d -P guitest:1
6d95689601b8(...)
docker ps
CONTAINER ID IMAGE COMMAND
6d95689601b8 guitest:1 "python test.py"
CREATED STATUS PORTS NAMES
4 seconds ago Up 2 seconds 0.0.0.0:32771->5000/tcp loving_boyd
Dockerfile is OK.
Issue
And so when I'm logging into 0.0.0.0:32771 it says "Connection was reset"
I saw from docker FAQ that to correct this problem, i have to "change the service’s configuration on [my] localhost so that the service accepts requests from all IPs"
Ok I have solved all my problems! Thanks to #n2o
The problem was incorrect arguments for socketio.run(app)
Previous:
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# Code here #
if __name__ == "__main__":
socketio.run(app, port=5000)
Fixed:
import os
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# code here #
if __name__ == "__main__":
port = int(os.environ.get('PORT', 5000))
socketio.run(app, host='0.0.0.0', port=port)
I am creating an Flask-socketio app, in which I want to send socket when an OSC message is received, in order to receive it into a web app thanks to socketio.js
from flask import Flask, render_template, copy_current_request_context, current_app
from flask_socketio import SocketIO, emit, send
from OSC import OSCClient, OSCMessage, OSCServer
import time, threading
app = Flask(__name__)
socketio = SocketIO(app)
client = OSCClient()
client.connect( ("localhost", 62345))
receive_address = ('localhost', 62346)
server = OSCServer(receive_address)
# simple callback functions
def answer_handler(addr, tags, stuff, source):
with app.app_context():
socketio.emit('tempo', 1)
# adding callback functions to listener
server.addMsgHandler("/puredata", answer_handler)
if __name__ == '__main__':
#Start OSCServer in extra thread
st = threading.Thread( target = server.serve_forever )
st.daemon = True
st.start()
print('OSC server is started')
socketio.run(app, host='0.0.0.0')
Even if I don't get error message, the socket is not receive from the javascript side, because the emit function is called in another thread, and there is conflicts with the request context.
I tried several things according to some other stackoverflow tickets :
socketio = SocketIO(app, async_mode='threading')
Adding this line before handler function
#copy_current_request_context
Or recreate a socketio instance into the callback
def answer_handler(addr, tags, stuff, source):
socketio_connection = SocketIO(app)
with app.app_context():
socketio_connection.emit('tempo', 1)
But none of these solution is working, and I need to integrate solve this 'context' problem into my thread.
Note that :
socketio.emit('tempo', 1)
is working great out of this thread , and received in the javascript part