I am trying to get my Flask application to work with WSGI under Apache on RHEL 8. A flat file with no imports works fine, and the development server works fine, but WSGI returns module not found errors. This is my file strucuture:
/var/www/FLASKAPPS/myapp/
utility/
configuration.py
logging.py
__init__.py
Contents of init.py:
from flask import Flask, Response, request, abort
from flask_restful import Resource, Api, reqparse, inputs
from utility.configuration import Configuration
from utility.logger import Logger
app = Flask(__name__)
api = Api(app)
configuration = Configuration()
logger = Logger()
class Main(Resource):
#staticmethod
def get():
return {'message': 'Hello World.'}
api.add_resource(Main, '/')
if __name__ == "__main__":
app.run()
Running the Python test server works fine.
Accessing the server via WSGI on Apache gives the error:
File "/var/www/FLASKAPPS/myapp/__init__.py", line 6, in <module>
from utility.configuration import Configuration
No module named 'utility'
What do I need to do for WSGI to be able to see these modules?
Related
Usecase: I have a python flask app that runs background_function() before serving any requests on routes.
When I execute the flask app, I receive the error - RuntimeError: Working outside of application context. I receive the error since I try to get the application context before any request is served.
What is the best pythonic way to execute the background_function() in this example?
from flask import Flask
from download import Download
app = Flask(__name__)
app.config.from_pyfile('config.py')
# run backgroung function
Download.background_function()
#app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
app.run()
The config file
FILE_LOCATION = os.environ['FILE_LOCATION'] # "file/path/on/server"
# Many other variables are present in this file
The download file
from flask import current_app as app
class Download:
#staticmethod
def background_function():
file_path = app.config["FILE_LOCATION"]
# code to download file from server to local
return
Try this:
from flask import Flask
from download import Download
app = Flask(__name__)
#app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
Download.background_function()
app.run()
the download file
from flask import current_app as app
class Download:
#staticmethod
def background_function():
print("testing")
given output:
testing
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
As you can see, the function runs first and prints testing and then runs the application.
trying to host my flask app (run.py) on PythonAnywhere. Have my virtualenv setup and all of my modules imported via pip. The flask app is stored at this location:
/home/goldsilvermonitor/GSM/run.py
Set up my WSGI file and it keeps giving my the error:
TypeError: 'module' object is not callable
My flask file look like this: (run.py)
from flask import Flask, flash, redirect, render_template, request, session, abort, url_for
app = Flask(__name__)
# ./Home Script:
#app.route("/")
#app.route("/index")
def index():
return render_template('index.html')
# ./Disclaimer Page:
#app.route("/disclaimer")
def disclaimer():
return render_template('disclaimer.html')
# ./data.xml:
app.route("/dataxml")
def dataxml():
return render_template('data.xml')
# ./404 Page
#app.errorhandler(404)
def page_not_found(e):
# 404 status set explicitly
return render_template('404.html'), 404
# FLask Debug Script:s
if __name__ == "__main__":
app.run(host="0.0.0.0", port='5000', debug=True)
And my WSGI file looks like this:
# +++++++++++ FLASK +++++++++++
# Flask works like any other WSGI-compatible framework, we just need
# to import the application. Often Flask apps are called "app" so we
# may need to rename it during the import:
#
#
import sys
#
## The "/home/goldsilvermonitor" below specifies your home
## directory -- the rest should be the directory you uploaded your Flask
## code to underneath the home directory. So if you just ran
## "git clone git#github.com/myusername/myproject.git"
## ...or uploaded files to the directory "myproject", then you should
## specify "/home/goldsilvermonitor/myproject"
path = '/home/goldsilvermonitor/GSM'
if path not in sys.path:
sys.path.append(path)
#
import run as application # noqa
#
# NB -- many Flask guides suggest you use a file called run.py; that's
# not necessary on PythonAnywhere. And you should make sure your code
# does *not* invoke the flask development server with app.run(), as it
# will prevent your wsgi file from working.
I have no idea what is causing this error. Have tried reuploading the files, redoing the WSGI config. But to no avail. If someone could help me then that would be great! Also should I remove the debug=true from the flask file before I go live?
You're trying to import a module (the file run.py) and then use it as an application; the application is the app object in that file, so in the WSGI file you should replace this:
import run as application # noqa
...with this:
from run import app as application # noqa
I have the following app which when I run using
flask run
seems to execute without error but when I perform python app.py gives me the following error:
➣ $ python app.py
Traceback (most recent call last):
File "app.py", line 14, in <module>
app.secret_key = os.environ['SECRET_KEY']
File "/Users/pkaramol/Workspace/second_flask/venv/bin/../lib/python3.7/os.py", line 678, in __getitem__
raise KeyError(key) from None
KeyError: 'SECRET_KEY'
#!/usr/bin/env python
import os
from flask import Flask
from flask_jwt import JWT, jwt_required
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy
import settings
from resources.item import Item, ItemList
app = Flask(__name__)
api = Api(app)
app.config.from_pyfile('settings.py')
app.secret_key = os.environ['SECRET_KEY']
db = SQLAlchemy(app)
if __name__ == "__main__":
print("Starting flask app...")
print(os.end['SECRET_KEY'])
db.create_all()
api.add_resource(Item, '/item/<string:name>')
api.add_resource(ItemList, '/items')
What is the difference in the two ways of running the flask app and why in the second case the environment is not rendered appropriately?
I am using python-dotenv to inject env vars from .env file
btw in the first case where the app starts without errors, I do not see the print statement I use for debug.
and if in the case of flask run the code below if __name__ == '__main__' is not called, how will I initialise my db by calling db.create_all()?
Replace app.secret_key assignment with arbitrary string.
I am permit you to ask you about a problem that I have with hosting flask application with your portage of mod_wsgi on windows
I have two flask application and only one can be alive a the same times due to conflict in import
ie :
If a request application 1 I have a response
Then if I request application 2 I have internal server error with error in log ...
Then if I restart apache and I request application 2 I have a response but if I request application 1 I have the same internal server error
If I comments some import like numpy both application can be alive at the same time
Any help would be appreciated if you have any idea or link or answer to about this problem?
My installation is describe below
Thanks by advance for tour times and your works
Alexandre
LOG of the error
mod_wsgi (pid=4936): Failed to exec Python script file 'D:/exec/Apache24/htdocs/wsgi/api_test_2.wsgi'.
mod_wsgi (pid=4936): Exception occurred processing WSGI script 'D:/exec/Apache24/htdocs/wsgi/api_test_2.wsgi'.
Traceback (most recent call last):
File "D:/exec/Apache24/htdocs/wsgi/api_test_2.wsgi", line 3, in
from api_test_2 import app as application
File "D:/exec/wsgi_api/api_test_2\api_test_2.py", line 2, in
import numpy
File "c:\python\python36\lib\site-packages\numpy\__init__.py", line 142, in
from . import core
File "c:\python\python36\lib\site-packages\numpy\core\__init__.py", line 16, in
from . import multiarray
File "c:\python\python36\lib\site-packages\numpy\core\multiarray.py", line 12, in
from . import overrides
File "c:\python\python36\lib\site-packages\numpy\core\overrides.py", line 46, in
""")
RuntimeError: implement_array_function method already has a docstring
#---------------------------------
# file : D:/exec/wsgi_api/api_test_1/api_test_1.py
#---------------------------------
from flask import Flask, jsonify,render_template, request, make_response
import numpy
app = Flask(__name__)
#app.route('/')
def home():
resp = make_response("hello from 1", 200)
resp.headers['Content-Type'] = 'charset=utf-8'
return resp
#---------------------------------
#---------------------------------
# file : D:/exec/wsgi_api/api_test_2/api_test_2.py
#---------------------------------
from flask import Flask, jsonify,render_template, request, make_response
import numpy
app = Flask(__name__)
#app.route('/')
def home():
resp = make_response("hello from 2", 200)
resp.headers['Content-Type'] = 'charset=utf-8'
return resp
if __name__ == '__main__':
app.run(host='127.0.0.1', port=36000)
#---------------------------------
I have this two wsgi file in appache httpdocs
#---------------------------------
# file : D:/exec/Apache24/htdocs/wsgi/api_test_1.wsgi
#---------------------------------
import sys
sys.path.append('D:/exec/wsgi_api/api_test_1/')
from api_test_1 import app as application
#---------------------------------
#---------------------------------
# file : D:/exec/Apache24/htdocs/wsgi/api_test_2.wsgi
#---------------------------------
import sys
sys.path.append('D:/exec/wsgi_api/api_test_1/')
from api_test_1 import app as application
#---------------------------------
#---------------------------------
In D:/exec/Apache24/conf/httpd.conf i add the line
#---------------------------------
WSGIScriptAlias /api_test_1 "D:/exec/Apache24/htdocs/wsgi/api_test_1.wsgi"
WSGIScriptAlias /api_test_2 "D:/exec/Apache24/htdocs/wsgi/api_test_2.wsgi"
#---------------------------------
I had a similar issue in a project. In my case, I had to add WSGIApplicationGroup %{GLOBAL} inside the .conf file of my site.
This is the documentation where I found the information:
https://modwsgi.readthedocs.io/en/develop/user-guides/checking-your-installation.html#sub-interpreter-being-used
I had a discussion on the mod_wsgi mailing list and I had the same response The explanation is numpy doesn't work in Python sub interpreters as the C extension modules are not implement properly to allow that, thus for mod_wsgi you can only use numpy in the main interpreter context, forced by the 'WSGIApplicationGroup %{GLOBAL}' directive
This is linked with the subject https://github.com/numpy/numpy/issues/3961
Try putting this in your WSGI configuration file:
single-interpreter = true
This works for me
i add WSGIApplicationGroup %{GLOBAL} in apache config file which is available in site-enabled folder.
Here's a simple Flask app with a syntax error (it should be sys.version, not sys.version()
from flask import Flask, url_for, request, render_template
import sys
app = Flask(__name__)
app.config.from_object(__name__)
#app.route('/')
def index():
version = sys.version()
return "This is the index page. Python version info: {}".format(version)
if __name__ == '__main__':
app.run(debug=True)
When I run it locally and try to access http://localhost:5000, I get the nice Werkzeug debugger:
but when I run it on a remote server (Apache 2.4.17, mod_wsgi 4.4.21), I only get a generic 500 error page:
I've tried various things to make this work:
set app.debug = True right after app = Flask(__name__)
based on this link, I tried adding this code as well:
from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(app, True)
but nothing seems to help.
I know that the debugger doesn't work in forked environments, but according to this link, the default mode for mod_wsgi is to not be forked. My Apache config is:
WSGIDaemonProcess flasktest user=david group=devgrp threads=1 python-path=/apps/www/80/wsgi-scripts/FlaskTest:/apps/.virtualenvs/flasktest/lib/python3.4/site-packages
So why can't I get the pretty debugger?
EDIT: Here's the modified file with my additions (that aren't working)
from flask import Flask
import sys
app = Flask(__name__)
app.config.from_object(__name__)
app.debug = True
from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(app, True)
#app.route('/')
def index():
version = sys.version()
return "This is the index page. Python version info: {}".format(version)
if __name__ == '__main__':
app.run(debug=True)
To add WSGI middleware to a Flask app, wrap and replace the app's wsgi_app attribute. In the case of the debug middleware, set app.debug = True as well so that Flask doesn't convert exceptions to 500 responses.
app.debug = True
app.wsgi_app = DebuggedApplication(app.wsgi_app, evalex=True)
It is a security risk to run the debugger on a public server. Despite the recent change requiring a PIN before running code, the debugger may still be insecure in unforseen ways. Typically, you get information about errors in production by using logging. This answer is a good basic summary of how to set that up.
Your method would probably work if you had replaced app rather than calling it application. mod_wsgi was probably picking up app before application, so it was still running the original app. It's still recommended to wrap app.wsgi_app though.