I am trying to use WebApp2 outside of AppEngine and can't find anywhere in the documentation how to set up static routes to files.
For example, I have the following folder structure
Presentation
-->js
-->-->main.js
-->templates
-->-->index.html (loaded via Jinja)
How do I reference the main.js as using ../js/main.js gives me a 404
Here's the documentation that deals with this: Quick start (to use webapp2 outside of App Engine). Did this not work?
Serving static files should occur outside of your WSGI application (the webapp2 app), so it depends on what server you are using to run your webapp2 app (which is a WSGI app), because that server will need to be configured to serve the static files. Could you please add to your question what kind of server you are using, and/or how you are running the webapp2 app?
Appreciate your response, found similar after much digging. Problem was my lack of understanding of exactly what WebApp2 was as normal point AppEngine Dev App Server at it.
I only need a simple HTTP server, so doing the following
static_app = StaticURLParser("Presentation/")
# Create a cascade that looks for static files first, then tries the webapp
app = Cascade([static_app, web_app])
def main():
httpserver.serve(app, host='127.0.0.1', port='8080')
if __name__ == '__main__':
main()
and then run python main.py
Related
I am deploying Flask on CPanel, and basic configurations are working correctly,
up to the point that I can access home route, defined as:
#app.route("/home")
#app.route("/")
def home():
return "This is home page, blah blah blah"
The site can be thought of, as being accessed at
https://sub-domain.main-domain.com/base-url,
thus, home page is accessed as https://sub-domain.main-domain.com/base-url/ and that works perfectly.
Problem
So, the issue comes when I access any other route, other than the slash("/"),
in the above example, for instance, accessing
https://sub-domain.main-domain.com/base-url/home,
doesn't seem to work at all, and results in
The configuration file does not exist. error.
Any possible help would be kindly appreciated. my passenger_wsgi.py is configured as:
import sys
# add your project directory to the sys.path
base_dir = u'/home/cpaneusername/base-dir'
if base_dir not in sys.path:
sys.path = [base_dir] + sys.path
# import flask app but need to call it "application" for WSGI to work
from app import website as application
Nevertheless, thanks for the assistance.
What I can suggest resolving the issue is to change the base URL of your Python app and remove any sub-folders from it. For example, just keep it that way:
https://sub-domain.main-domain.com/
And try again.
Otherwise, you might want to change the /home route of your app to this one instead:
#app.route("/base-url/home")
If none of the above works, then make sure that you have the correct .htaccess rules in place to forward the requests properly to your app, but I assume you already have considering the fact that you are able to access the / of the app.
I tried moving the Python app and other supporting modules to /public folder, and in the wsgi file, I imported as
from public.app import website as application
There, it worked.
Consider, I have a flask server deployed which routes to multiple webpages. If I want to change content of one route, by changing its code, is it possible to reflect those changes in webpages without rerunning the flask server? It is possible to host and rerun other scripts on the linux server or entriely another flask server as long as the website url(port number and route) doesn't change.
Please suggest any way you can come up with!
setting flask environment will do the thing for you in the shell.
export FLASK_ENV=development
Assuming you are using flask development server,
Yes, its possible using use_reloader=True,
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
# You business logic code
return some_data
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0', port=8000,
use_reloader=True, threaded=True)
However it is not good idea to use it in production, related Is the server bundled with Flask safe to use in production?
My assumption is that you want your deployment service to recognize that a change has occurred in a file, which prompts it to automatically restart to reflect the changes, rather than you manually restarting the service.
Assuming that you are deploying on a production uWSGI server, starting the service with touch-reload=/path/to/folder would allow uWSGI to reload when the specified file/folder is modified or touched. https://uwsgi-docs.readthedocs.io/en/latest/Options.html#touch-reload
--touch-reload=/path/to/file.txt
I think you can only do this with the Apache Webserver. Refer to the Flask documentation.
I haven't tried it (yet), but when you have deployed your new code any small change in the wsgi-file should automatically reload the code.
You mentioned two requirements
I have a flask server deployed
I would assume you mean it is deployed in a production environment. This automatically rules out debug-mode from the development server, because it is not stable, efficient or secure for production use.
Without rerunning the flask server
This rules out autoreload, because this will completely restart your server. Any requests that come in until the server is ready again will fail.
One way of going about is by running your application with debug mode ON through app.run(debug=True)
The problem with this approach is that your application would be exposed over the internet with the application's internal debugger on which shouldn't be done.
A better way I can think of is to call the functions you need to change frequently from a different file other than where your core flask code exists and change in that file whenever needed. This way you don't need to change your Flask code and you won't need to restart the application
Edit:
A sample Flask route would be
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
# Route's business logic usually goes here
return data
Now, instead of writing your application's business logic in the same file as your route, you could simply write it in a different file as follows and import it in the file with the route:
File with the business logic
def process_hello_world(params):
# Write your business logic here which you want to change without reloading the application
return data
And in the application file with the route call the business logic as follows:
from flask import Flask
from
app = Flask(__name__)
#app.route('/')
def hello_world():
data = process_hello_world()
return data
I'm trying to deploy a Flask app within Azure, using the pre made template created by Azure.
I can't get a simple...
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run()
To do anything. To simplify further still, even the pre made deployment returns an error...
Clearly I'm misunderstanding something very fundamental here.
Using FTP I can see the files that Azure is creating - sure does look like there should be a nice little demo site.
What am I doing wrong?
Cheers, Ben
According to your description, I think the issue was caused by some incorrect configuration in the web.config & the Application Settings of your WebApp settings. Please try to refer to the blog to resolve it.
Meanwhile, I don't know what pre made template created by Azure you used. I tried to create a new Azure WebApp for Flask as below.
The file list in the wwwroot path in the Kudu tool or FTP shown as below.
Then, I modified the code views.py in the FlaskWebProject1 directory. And it works.
It seems to be more simple. Hope it helps.
I've been figthing the same issue for a while, I have only be able to workaround it by changing the pricing tier associated to the "service plan" to S2 Standard. If I try to use S1 Standard I run into the same issues.
In my development of Android and Java applications I have been using PHP scripts to interact with an online MySQL database, but now I want to migrate to Python.
How does one run Python scripts on a web server? In my experience with PHP, I have been saving my files under /var/www folder in a Linux environment. Then I just call the file later with a URL of the path. Where do I save my Python scripts?
You can use Flask to run webapps.
The simple Flask app below will help you get started.
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/sampleurl' methods = ['GET'])
def samplefunction():
#access your DB get your results here
data = {"data":"Processed Data"}
return jsonify(data)
if __name__ == '__main__':
port = 8000 #the custom port you want
app.run(host='0.0.0.0', port=port)
Now when you hit http://your.systems.ip:8000/sampleurl you will get a json response for you mobile app to use.
From within the function you can either do DB reads or file reads, etc.
You can also add parameters like this:
#app.route('/sampleurl' methods = ['GET'])
def samplefunction():
required_params = ['name', 'age']
missing_params = [key for key in required_params if key not in request.args.keys()]
if len(missing_params)==0:
data = {
"name": request.argv['name'],
"age": request.argv['age']
}
return jsonify(data)
else:
resp = {
"status":"failure",
"error" : "missing parameters",
"message" : "Provide %s in request" %(missing_params)
}
return jsonify(resp)
To run this save the flask app in a file e.g. myapp.py
Then from terminal run python myapp.py
It will start the server on port 8000 (or as specified by you.)
Flask's inbuilt server is not recommended for production level use. After you are happy with the app, you might want to look into Nginx + Gunicorn + Flask system.
For detailed instruction on flask you can look at this answer. It is about setting up a webserver on Raspberry pi, but it should work on any linux distro.
Hope that helps.
Use a web application framework like CherryPy, Django, Webapp2 or one of the many others. For a production setup, you will need to configure the web server to make them work.
Or write CGI programs with Python.
On Apache the simplest way would be to write the python as CGI here is an example:
First create an .htaccess for the web folder that is serving your python:
AddHandler cgi-script .py
Options +ExecCGI
Then write python that includes some some cgi libraries and outputs headers as well as the content:
#!/usr/bin/python
import cgi
import cgitb
cgitb.enable()
# HEADERS
print "Content-Type:text/html; charset=UTF-8"
print # blank line required at end of headers
# CONTENT
print "<html><body>"
print "Content"
print "</body></html>"
Make sure the file is owned by Apache chown apache. filename and has the execute bit set chmod +x filename.
There are many significant benefits to actually using a web framework (mentioned in other answers) over this method, but in a localhost web server environment set up for other purposes where you just want to run one or two python scripts, this works well.
Notice I didn't actually utilize the imported cgi library in this script, but hopefully that will direct you to the proper resources.
Most web development in python happens using a web framework. This is different than simply having scripts on the server, because the framework has a lot more functionality, such as handling URL routing, HTML templating, ORM, user session management, CSRF protection, and a lot of other features. This makes it easier to develop web sites, especially since it promotes component reuse, in a OOP fashion.
The most popular python web framework is Django. It's a fully-featured, tighly-coupled framework, with lots of documentation available. If you prefer something more modular and easier to customize, I personally recommend Flask. There's also lots of other choices available.
With that being said, if all you really want is to run a single, simple python script on a server, you can check this question for a simple example using apache+cgi.
Per suggestions on SO/SF and other sites, I am using CherryPy as the WSGI server to launch multiple instances of a Python web server I built with Flask. Each instance runs on its own port and sits behind Nginx. I should note that the below does work for me, but I'm troubled that I have gone about things the wrong way and it works "by accident".
Here is my current cherrypy.conf file:
[global]
server.socket_host = '0.0.0.0'
server.socket_port = 8891
request.dispatch: cherrypy.dispatch.MethodDispatcher()
tree.mount = {'/':my_flask_server.app}
Without diving too far into my Flask server, here's how it starts:
import flask
app = flask.Flask(__name__)
#app.route('/')
def hello_world():
return "hello"
And here is the command I issue on the command line to launch with Cherryd:
cherryd -c cherrypy.conf -i my_flask_server
Questions are:
Is wrapping Flask inside CherryPy still the preferred method of using Flask in production? https://stackoverflow.com/questions/4884541/cherrypy-vs-flask-werkzeug
Is this the proper way to use a .conf file to launch CherryPy and import the Flask app? I have scoured the CherryPy documentation, but I cannot find any use cases that match what I am trying to do here specifically.
Is the proper way to launch multiple CherryPy/Flask instances on a single machine to execute multiple cherryd commands (daemonizing with -d, etc) with unique .conf files for each port to be used (8891, 8892, etc)? Or is there a better "CherryPy" way to accomplish this?
Thanks for any help and insight.
I can't speak for Flask, but I can for CherryPy. That looks like the "proper way"...mostly. That line about a MethodDispatcher is a no-op since it only affects CherryPy Applications, and you don't appear to have mounted any (just a single Flask app instead).
Regarding point 3, you have it right. CherryPy allows you to run multiple Server objects in the same process in order to listen on multiple ports (or protocols), but it doesn't have any sugar for starting up multiple processes. As you say, multiple cherryd commands with varying config files is how to do it (unless you want to use a more integrated cluster/config management tool like eggmonster).
Terminology: Mounting vs Grafting
In principle this is a proper way to serve a flask app through cherrypy, just a quick note on your naming:
It is worth noting here that tree.mount is not a configuration key by itself - tree will lead to cherrypy._cpconfig._tree_config_handler(k, v) being called with the arguments 'mount', {'/': my_flask_server.app}.
The key parameter is not used at all by the _tree_config_handler so in your config "mount" is just an arbitrary label for that specific dict of path mappings. It also does not "mount" the application (it's not a CherryPy app after all). By that I mean, it does not cherrypy.tree.mount(…) it but rather cherrypy.tree.grafts an arbitrary WSGI handler onto your "script-name" (paths, but in CherryPy terminology) namespace.
Cherrypy's log message somewhat misleadingly says "Mounted <app as string> on /"]
This is a somewhat important point since with graft, unlike mount, you cannot specify further options such as static file service for your app or streaming responses on that path.
So I would recommend changing the tree.mount config key to something descriptive that does not invite reading too much semantics about what happens within CherryPy (since there is the cherrypy.tree.mount method) due to that config. E.g., tree.flask_app_name if you're just mapping that one app in that dict (there can be many tree directives, all of them just getting merged into the paths namespace) or tree.wsgi_delegates if you map many apps in that dict.
Using CherryPy to serve additional content without making an app of it
Another side note, if you want cherrypy to e.g. provide static file service for your app, you don't have to create a boilerplate cherrypy app to hold that configuration. You just have to mount None with the appropriate additional config. The following files would suffice to have CherryPy to serve static content from the subdirectory 'static' if they are put into the directory where you launch cherryd to serve static content (invoke cherryd as cherryd -c cherrypy.conf -i my_flask_server -i static:
static.py
import cherrypy
# next line could also have config as an inline dict, but
# file config is often easier to handle
cherrypy.tree.mount(None, '/static-path', 'static.conf')
static.conf
# static.conf
[/]
tools.staticdir.on = True
tools.staticdir.root = os.getcwd()
tools.staticdir.dir = 'static'
tools.staticdir.index = 'index.html'