FlaskApp returning http 500 in apache with mod_wsgi

FlaskApp returning http 500 in apache with mod_wsgi

I’m trying to host my python 3.4 flask app through apache and mod_wsgi. Running the app through flasks own server works fine. The app was made in a virtual environment, pyvenv-3.4.
However, when trying to connect to the apache server in a browser, it throws a 500 http error. Configs and logs are attached. I think this has to do with using pyvenv and not virtualenv (from pip).
Flask documentation tells me to activate the virtual environment using this line
activate_this = ‘/path/to/env/bin/activate_this.py’

however, that produces an IOError as the file does not exist. I tried pointing it to the ‘activate’-file instead, and activate.csh, activate.fish, with no luck. All files produces SyntaxError on the deactivate-line.
How can I run this app through Apache with my virtualenv?
flaskapp.wsgi
#!/usr/bin/python
activate_this = ‘/var/www/FlaskApp/FlaskApp/bin/activate’
execfile(activate_this, dict(__file__=activate_this))
import sys
import logging

logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,”/var/www/FlaskApp/”)

from FlaskApp import app as application
application.secret_key = ‘some secret key’

Apache VirtualHost

ServerName example.org # my server name
ServerAlias gallifrey 192.168.0.84
ServerAdmin admin@example.org # my admin
WSGIScriptAlias /flask /var/www/FlaskApp/flaskapp.wsgi

Order allow,deny
Allow from all

Alias /static /var/www/FlaskApp/FlaskApp/static

Order allow,deny
Allow from all

ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined

Hierarchy
/var/www/FlaskApp
flaskapp.wsgi
FlaskApp/
bin/
activate
activate.csh
activate.fish
easy_install, easy_install-3.4
pip, pip3, pip3.4
python, python3, python3.4
include/
lib/
scripts/
static/
templates/
app.py
__init__.py

Trying to open the webpage I get a http 500 error:
Apache error.log
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] mod_wsgi (pid=31629): Target WSGI script ‘/var/www/FlaskApp/flaskapp.wsgi’ cannot be loaded as Python module.
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] mod_wsgi (pid=31629): Exception occurred processing WSGI script ‘/var/www/FlaskApp/flaskapp.wsgi’.
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] Traceback (most recent call last):
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] File “/var/www/FlaskApp/flaskapp.wsgi”, line 3, in
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] execfile(activate_this, dict(__file__=activate_this))
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] File “/var/www/FlaskApp/FlaskApp/bin/activate”, line 4
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] deactivate () {
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] ^
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] SyntaxError: invalid syntax

Related:  Mod_pagespeed delete cache?

Solutions/Answers:

Solution 1:

You can either follow the VirtualEnvironments instructions, or you can replicate what virtualenv‘s activate_this.py script does:

import sys
import os

old_os_path = os.environ['PATH']
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if sys.platform == 'win32':
    site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
    site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
    if item not in prev_sys_path:
        new_sys_path.append(item)
        sys.path.remove(item)
sys.path[:0] = new_sys_path

You could make this a more general function:

import sys
import os

def activate_venv(path):
    if sys.platform == 'win32':
        bin_dir = os.path.join(path, 'Scripts')
        site_packages = os.path.join(base, 'Lib', 'site-packages')
    else:
        bin_dir = os.path.join(path, 'bin')
        site_packages = os.path.join(BASE, 'lib', 'python%s' % sys.version[:3], 'site-packages')
    os.environ['PATH'] = bin_dir + os.pathsep + os.environ['PATH']
    prev_sys_path = list(sys.path)
    import site
    site.addsitedir(site_packages)
    sys.prefix, sys.real_prefix = path, sys.prefix

    # Move the added items to the front of the path:
    new_sys_path = []
    for item in list(sys.path):
        if item not in prev_sys_path:
            new_sys_path.append(item)
            sys.path.remove(item)
    sys.path[:0] = new_sys_path

Put that in a module on your default Python module search path, import activate_venv and pass in the result of os.path.dirname(os.path.abspath(__file__)):

from somemodule import activate_venv
import os.path
activate_venv(os.path.dirname(os.path.abspath(__file__)))

Solution 2:

Did you try:

WSGIPythonHome /var/www/FlaskApp

and just have mod_wsgi handle setting it up or you?

Solution 3:

When you use a Python virtual environment, with applications like Django or Flask you have to make sure Apache picks up the location of the WSGI path.

If you have a Debian distro and used the package manager to install Apache you should have a directory structure for the config files like this:
/etc/apache2/.

Edit a VirtualHost config file (e.g. AppName.conf) under “/etc/apache2/sites-available/AppName.conf” and follow the example below for a Flask app under Python v3.5:

WSGIPythonPath /<PATH_OF_PYTHON_VIRTUAL_ENVIRONMENT>/lib/python3.5/site-packages
<VirtualHost *:80>
        ServerName <HOST or IP_ADDRESS>
        ServerAdmin your-email@domain.com
        WSGIScriptAlias / /var/www/app_name/your_wsgi_app.wsgi
        WSGIPassAuthorization On
        <Directory /var/www/app_name/AppName/>
                Order allow,deny
                Allow from all
        </Directory>
        Alias /static /var/www/app_name/AppName/static
        <Directory /var/www/app_name/AppName/static/>
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        # e.g. LogLevel debug
        LogLevel <info|warn|error|debug>
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Solution 4:

I tried to add this above and outside in /etc/httpd/conf/httpd.conf and it worked.

WSGIPythonPath /your_virtualenv/lib/python2.7/site-package

Related:  NGINX with Tomcat configuration

References