I'm trying to automate the running of a script. Unfortunately, when I deploy to Heroku, my script doesn't run. I have attached the code for my server. 'newsAgg' is a reference to my script.
Can anyone clear up why my script file is not run when deployed? (It works locally)
from flask import Flask
import newsAgg as N
import threading
import os
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t
newsInterval = set_interval(N.init, 3600)
N.init()
newsInterval()
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
Related
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)
I'm trying to build a Flask app with Gunicorn to serve concurrent requests. For what it's worth, the context is a bring-your-own-container Sagemaker application.
The issue is that I need the application to periodically check for updates. So I thought to implement a thread for this. Here is a minimal example of some Flask code with an update thread.
server.py
from flask import Flask
import time, threading
app = Flask(__name__)
message = True
def update():
while True:
message = not message
time.sleep(10)
#app.route("/")
def hello():
global message
return message
update_thread = threading.Thread(target=update)
if __name__ == "__main__":
update_thread.start()
app.run()
update_thread.join()
I then launch with gunicorn:
gunicorn -k gevent -b unix:/tmp/gunicorn.sock -w 4 server:app
Perhaps unsurprisingly the update thread doesn't start since the __main__ section is never executed.
Question: How can one use an update thread (or similar construct) in a Flask app with Gunicorn?
It looks like this can be accomplished using Flask-APScheduler as follows:
pip install flask_apscheduler
server.py
from flask import Flask
from apscheduler.schedulers.background import BackgroundScheduler
import atexit
app = Flask(__name__)
message = True
def update():
global message
message = not message
scheduler = BackgroundScheduler()
scheduler.add_job(func=update,trigger="interval",seconds=10)
scheduler.start()
# shut down the scheduler when exiting the app
atexit.register(scheduler.shutdown)
#app.route("/")
def hello():
global message
return message
if __name__ == "__main__":
app.run()
Then launching as usual with
gunicorn -k gevent -b unix:/tmp/gunicorn.sock -w 4 server:app
I haven't found a way to set a handler to detect when a flask server is already running. Consider the following code snippet:
import flask
import requests
def on_start():
# send a request to the server, it's safe to do so
# because we know it's already running
r = requests.get("http://localhost:1234")
print(r.text) # hello world
app = flask.Flask(__name__)
#app.route("/")
def hello():
return "hello world"
app.run(port=1234, host="localhost", on_start=on_start)
The last line fails because on_start is not an argument of run, but hopefully you get the idea of what I'm trying to do. How can I do it?
What you can do is wrap the function that you want to kick off with before_first_request decorator as found here ==> http://flask.pocoo.org/docs/1.0/api/#flask.Flask.before_first_request
However, it won't get kicked off until someone makes a request to the server but you can do something like this:
import requests
import threading
import time
from flask import Flask
app = Flask(__name__)
#app.before_first_request
def activate_job():
def run_job():
while True:
print("Run recurring task")
time.sleep(3)
thread = threading.Thread(target=run_job)
thread.start()
#app.route("/")
def hello():
return "Hello World!"
def start_runner():
def start_loop():
not_started = True
while not_started:
print('In start loop')
try:
r = requests.get('http://127.0.0.1:5000/')
if r.status_code == 200:
print('Server started, quiting start_loop')
not_started = False
print(r.status_code)
except:
print('Server not yet started')
time.sleep(2)
print('Started runner')
thread = threading.Thread(target=start_loop)
thread.start()
if __name__ == "__main__":
start_runner()
app.run()
Details & Source via Google-fu: https://networklore.com/start-task-with-flask/
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)
Why this code is not running on heroku? (Internal server error)
import os
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
a = 10
b = 20
c = a + b
return c
if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 5000.
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
Logs:
Starting process with command python app.py
a = 1
^
SyntaxError: invalid syntax
File "app.py", line 8
This code is working (Python hello world from heroku guides)
import os
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return 'Hello World!'
if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 5000.
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
Sounds like that not your code is being executed. After all your line was a = 10 and the log file complains about a line stating a = 1.
Or maybe there's a strange (invisible?) character between the 1 and the 0.
I'd propose to change that value from 10 to 42 for testing and see in what way the error log message changes.