web.py - specify address and port - python

How to specify listening address and port in web.py? Something like:
web.application( urls, host="33.44.55.66", port=8080 )
Edit
I would like to avoid using the default web.py command line parsing

From API docmentation of web.py:
module web.httpserver
function runsimple(func,server_address=('0.0.0.0', 8080))
Runs CherryPy WSGI server hosting WSGI app func. The directory static/ is hosted statically.
Example code
import web
class MyApplication(web.application):
def run(self, port=8080, *middleware):
func = self.wsgifunc(*middleware)
return web.httpserver.runsimple(func, ('0.0.0.0', port))
if __name__ == "__main__":
app = MyApplication(urls, globals())
app.run(port=8888)

If you're using web.py's built-in webserver, you can just append the port to the command:
python app.py 8080
I haven't tried ever with the listening address, but perhaps it will accept 1.2.3.4:8080 as the format.

you can see the follow code in wsgi.py:
server_addr = validip(listget(sys.argv, 1, ''))
if os.environ.has_key('PORT'): # e.g. Heroku
server_addr = ('0.0.0.0', intget(os.environ['PORT']))
return httpserver.runsimple(func, server_addr)
so, you can set the web server port by add environ variable:
import os
os.environ["PORT"] = "80"

URLS = ("/", index)
class index:
def GET:
....
if __name__ == "__main__":
app = web.application(URLS, globals())
web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", 8888))

Related

How to run Python WSGIServer using gunicorn?

I have implemented a simple Flask-like framework using HTTPServer and BaseHTTPRequestHandler from http.server for educational purposes.
I have found out that I can replace HTTPServer with WSGIServer from wsgiref.simple_server and the code runs without any other modification.
The run method of my implementation works as follows:
def run(self, host: str, port: int):
web_server = WSGIServer((host, port), Request)
try:
print("Server is running at port", port)
web_server.serve_forever()
except KeyboardInterrupt:
web_server.server_close()
print("Server stopped")
When I read the gunicorn docs, I have found out that gunicorn expects a function like this:
def app(environ, start_response):
"""Simplest possible application object"""
data = b'Hello, World!\n'
status = '200 OK'
response_headers = [
('Content-type', 'text/plain'),
('Content-Length', str(len(data)))
]
start_response(status, response_headers)
return iter([data])
And that wsgiref.simple_server.make_server takes a function like the above and instantiates a WSGIServer and calls the serve_forever() method like I did in my implementation.
I have tried to return the app from thr WSGIServer from the WSGIServer.get_app() method but it returns None.
I would like to know how to run my WSGIServer class using gunicorn from the terminal.
If you have a framework-like app, then one best way to serve it is to wrap the framework entry point as a callable class, and pass this as a whole to gunicorn.
Here are examples for Waitress web server and Gunicorn web server how to make it serve the same WSGI app
# Router.__call__() is the entry point for the request processing
def setup_app() -> Router:
context.init_console_logging()
app = create_app(production=True, oracle_context=context)
check_oracle_db()
check_web_db()
from tradingstrategy import __version__
from .api import version as api_version
logger.info("Server version is %s, client library version %s", api_version, __version__)
return app
# Waitress main entry point
def main():
app = setup_app()
port = int(os.environ.get("BACKEND_PORT", 3456))
scheme = os.environ.get("WSGI_SCHEME", "http")
logger.info("Matilda backend server starting at port %d", port)
serve(app,
host='127.0.0.1',
trusted_proxy="127.0.0.1",
threads=32,
port=port,
trusted_proxy_headers="forwarded",
url_scheme=scheme,
url_prefix='/api')
def gunicorn_entry_point() -> Router:
"""Gunicorn calls this function for every worker process.
To run::
gunicorn --bind 127.0.0.1:3456 --workers 1 --threads 1 "backend.server.server:gunicorn_entry_point()"
"""
app = setup_app()
return app
See Pyramid Router implementation for WSGI app. It is a good example to look upon if you are unsure how to deal with WSGI framework.
class Router:
# ...
def __call__(self, environ, start_response):
"""
Accept ``environ`` and ``start_response``; create a
:term:`request` and route the request to a :app:`Pyramid`
view based on introspection of :term:`view configuration`
within the application registry; call ``start_response`` and
return an iterable.
"""
response = self.execution_policy(environ, self)
return response(environ, start_response)

How to run flask server from another module?

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

Add Tensorboard server to Flask endpoint

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)

How can i make a python server open an html file as deafult instead of directory?

here is an example for a simple server:
import http.server
import socketserver
PORT = 80
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
the server itself works and the port is open but it opens the directory the code is in while i need it to open an html file that is in that directory.
How can i make it open the html file i want instead of the directory?
You can extend SimpleHTTPServer.SimpleHTTPRequestHandler and override the do_GET method to replace self.path with your_file.html if / is requested.
import SimpleHTTPServer
import SocketServer
class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.path = '/your_file.html'
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
Handler = MyRequestHandler
server = SocketServer.TCPServer(('0.0.0.0', 8080), Handler)
server.serve_forever()
More: Documentation

python bottle can run two programs on the same address and port on WINDOWS

I just encountered a weird issue about bottle on windows.
When I tested the my bottle codes, I found that it could run multiple same programs on WINDOWS using same address and port. But when you try to start multiple same program on the Linux or Mac using same address and port, it will report the below error:
socket.error: [Errno 48] Address already in use
my bottle codes are:
from bottle import route, run, template
#route('/hello/:name')
def index(name='World'):
return template('<b>Hello {{name}} </b>', name=name)
run(host='localhost', port=9999)
Then I traced the code, from bottle to wsgiref, and finnaly found that the problem might be in the Python27\Lib\BaseHTTPServer.py.
I mean when I use the the below simple codes:
import BaseHTTPServer
def run(server_class=BaseHTTPServer.HTTPServer,
handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
server_address = ('localhost', 9999)
print "start server on localhost 9999"
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
run()
The same issue would happen on windows.
But if I directly used the socketserver, like the below codes:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
print "Start a server on localhost:9999"
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
The same issue will not happen, I mean even on window the above socketserver codes will report the error, when you try to start another programe.
socket.error: [Errno 48] Address already in use
All my tests used the Python 2.7, Windows 7 and Centos 5.
So my questions are why the HTTPServer will have this issue on windows?
And how can I let my bottle programe will report the same error on windows, just like on windows?
Sorry to bother all.
I've found the resolution, just so simple.
Simply change the BaseHTTPServer.HTTPServer's attribute allow_reuse_address to 0.
The codes should be:
from bottle import route, run, template
import BaseHTTPServer
#route('/hello/:name')
def index(name='World'):
return template('<b>Hello {{name}} </b>', name=name)
setattr(BaseHTTPServer.HTTPServer,'allow_reuse_address',0)
run(host='localhost', port=9999)

Categories