I'm trying to get mongrel2 to work with m2wsgi. What I need to do so I can see "Hello World!" in my browser? Mongrel2 is installed but any site configurations are not done yet.
def app(environ, start_response):
start_response("200 OK", [('Content-Type', 'text/plain')])
return ['Hello World!', ]
Trying to run it:
m2wsgi test
AssertionError: the specified app is not callable
I'm running Ubuntu Maverick.
If Mongrel2 is not fully configured, as your "Mongrel2 is installed but any site configurations are not done yet" statement suggests, then it won't be able to find your app (the m2wsgi documentation is perhaps not as clear about this as it might be). Here's a tutorial on getting Mongrel2 set up and ready to connect to a WSGI app - it uses wsgid instead of m2wsgi, but I bet you can adapt it to your needs.
To m2wgi be able to load your app, it must be in your PYTHONPATH, so to be able to run your test app try copying the test.py module to somewhere in your PYTHONPATH or, easier, try this:
PYTHONPATH=.:$PYHTONPATH m2wsgi test.app tcp://127.0.0.1:9995
Assuming you have, in your mongrel2 config database, a route pointing to a handler with send_spec = tcp://127.0.0.1:9995 and recv_spec = tcp://127.0.0.1:9994. I tried this locally and it worked:
daltonmatos#jetta ~ [6]$ curl http://localhost/m2wsgi/
Hello World!daltonmatos#jetta ~ [7]$
Take a look at the blog post cited by Sean, you have a great idea on how to configure mongrel2 and setup your hosts/routes/handlers. Also give wsgid a try, maybe you like it =). It also has support for raw WSGI apps.
Gook luck and happy hacking!
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.
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.
I'm trying to get the URL that has been requested in Python without using a web framework.
For example, on a page (let's say /main/index.html), the user clicks on a URL to go to /main/foo/bar (/foo/bar doesn't exist). Apache (with mod_wsgi) then redirects the user to a PHP script at /main/, which then gets the url and searches MySQL for any matching fields. Then the rest of the field is returned. This helped in PHP:
$_SERVER["REQUEST_URI"];
I'd rather not use PHP since it's becoming increasingly difficult to maintain the PHP code whilst the database keeps changing in structure.
I'm pretty sure there's a better way altogether and any mention would be greatly appreciated. For the sake of relevancy, is this even possible (to get the requested URL in Python)? Should I just use a framework, although it seems quite simple?
Thanks in advance,
Jamie
Note: I don't want to use GET for security purposes.
Well, if you run your program as a CGI script, you can get the same information in os.environ. However, if I recall correctly, REQUEST_URI as such is not part of the CGI standard and you need to use os.environ['SCRIPT_NAME'], os.environ['PATH_INFO'] and os.environ['QUERY_STRING'] to get the equivalent data.
However, I seriously urge you to see some lightweight framework, such as Pyramid. Plain CGI with Python is slow and generally just pain in the ass.
Unlike PHP, Python is a general purpose language and doesn't have this built-in.
The way you can gather this information depends on the deployment solution:
CGI (mostly Apache with mod_python, deprecated): see #Antti Haapala solution
WSGI (most other deployment solutions): see #gurney alex solution
But you will encouter much more problems: session hanling, url management, cookies, and even juste simple POST/GET parsing. All of this need to be done manually if you don't use a framework.
Now, if you feel like a framework is overkill (but really, incredible tools like Django are worth it), you can use a micro framework like bottle.
Microframeworks will typically make this heavy lifting for you, but without the complicated setup or the additional advanced features. Bottle has actually zero setup an is a one file lib.
Hello word with bottle:
from bottle import route, run, request
#route('/hello/:name')
def index(name='World'):
return '<b>Hello %s! You are at %s</b>' % (name, request.path)
run(host='localhost', port=8080)
request.path contains what you want, and if you visit http://127.0.0.1:8080/hello/you, you will get:
Hello you! You are at /hello/you
When I want to get a URL outside of any framework using Apache2 and Mod_WSGI I use
environ.get('PATH_INFO')
inside of my application() function.
When using mod_python, if I recall correctly you can use something like:
from mod_python import util
def handler(request):
parameters = util.FieldStorage(request)
url = parameters.get("url", "/")
See http://www.modpython.org/live/current/doc-html/pyapi-util.html for more info on the mod_python.util module and the FieldStorage class (including examples)
Whilst developing I want to handle some things slight differently than I will when I eventually upload to the Google servers.
Is there a quick test that I can do to find out if I'm in the SDK or live?
See: https://cloud.google.com/appengine/docs/python/how-requests-are-handled#Python_The_environment
The following environment variables are part of the CGI standard, with special behavior in App Engine:
SERVER_SOFTWARE:
In the development web server, this value is "Development/X.Y" where "X.Y" is the version of the runtime.
When running on App Engine, this value is "Google App Engine/X.Y.Z".
In app.yaml, you can add IS_APP_ENGINE environment variable
env_variables:
IS_APP_ENGINE: 1
and in your Python code check if it has been set
if os.environ.get("IS_APP_ENGINE"):
print("The app is being run in App Engine")
else:
print("The app is being run locally")
Based on the same trick, I use this function in my code:
def isLocal():
return os.environ["SERVER_NAME"] in ("localhost", "www.lexample.com")
I have customized my /etc/hosts file in order to be able to access the local version by prepending a "l" to my domain name, that way it is really easy to pass from local to production.
Example:
production url is www.example.com
development url is www.lexample.com
I just check the httplib (which is a wrapper around appengine fetch)
def _is_gae():
import httplib
return 'appengine' in str(httplib.HTTP)
A more general solution
A more general solution, which does not imply to be on a Google server, detects if the code is running on your local machine.
I am using the code below regardless the hosting server:
import socket
if socket.gethostname() == "your local computer name":
DEBUG = True
ALLOWED_HOSTS = ["127.0.0.1", "localhost", ]
...
else:
DEBUG = False
ALLOWED_HOSTS = [".your_site.com",]
...
If you use macOS you could write a more generic code:
if socket.gethostname().endswith(".local"): # True in your local computer
...
Django developers must put this sample code in the file settings.py of the project.
EDIT:
According to Jeff O'Neill in macOS High Sierra socket.gethostname() returns a string ending in ".lan".
The current suggestion from Google Cloud documentation is:
if os.getenv('GAE_ENV', '').startswith('standard'):
# Production in the standard environment
else:
# Local execution.
Update on October 2020:
I tried using os.environ["SERVER_SOFTWARE"] and os.environ["APPENGINE_RUNTIME"] but both didn't work so I just logged all keys from the results from os.environ.
In these keys, there was GAE_RUNTIME which I used to check if I was in the local environment or cloud environment.
The exact key might change or you could add your own in app.yaml but the point is, log os.environ, perhaps by adding to a list in a test webpage, and use its results to check your environment.