4

I installed Flask on Python 2.7.12/Apache 2.4/Ubuntu 16.04.1 LTS. I've been using these two tutorials to get set up. I'm not running venv or any other virtual environment (unlike this post). Running a simple Flask app works fine (a la "hello world"). I have a flaskapp.wsgi and a flaskapp.py in the same directory (/var/www/html).

flaskapp.wsgi

import sys
sys.path.insert(0, "/var/www/html/flaskapp")
from flaskapp import app as application

flaskapp.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def main():
    return "hello world"

if __name__ == '__main__':
    app.run()

But when I try to import a module outside of the basic set of Flask modules, eg. httplib2 (which I installed via pip), I get a 500 HTTP error. Simply adding import httplib2 to flaskapp.py throws this error.

Looking at the Apache error logs I see the following:

[wsgi:error] mod_wsgi (pid=22739): Target WSGI script '/var/www/html/flaskapp/flaskapp.wsgi' cannot be loaded as Python module.
[wsgi:error] mod_wsgi (pid=22739): Exception occurred processing WSGI script '/var/www/html/flaskapp/flaskapp.wsgi'.
[wsgi:error] Traceback (most recent call last):
[wsgi:error] File "/var/www/html/flaskapp/flaskapp.wsgi", line 7, in <module>
[wsgi:error] from flaskapp import app as application
[wsgi:error] File "/var/www/html/flaskapp/flaskapp.py", line 7, in <module>
[wsgi:error] import httplib2
[wsgi:error] ImportError: No module named httplib2

When I run python (not using Flask), I can import httplib2 without trouble. So it seems for some reason my Flask app can't access pip's imports.

Here's what I've done to troubleshoot so far:

I checked to see where httplib2 lives, using __file__:

>>> import httplib2
>>> httplib2.__file__
'/home/andrew/.local/lib/python2.7/site-packages/httplib2/__init__.pyc'

Then I checked both sys.path and pip.get_installed_distributions() from within the Flask app:

flaskapp.py (revised)

from flask import Flask, jsonify
import pip, sys

modules = ""
for i in pip.get_installed_distributions():
    modules = modules + " " + str(i)

app = Flask(__name__)

@app.route('/')
def main():
    return jsonify({ "modules":modules, "sys.path":sys.path })

if __name__ == '__main__':
    app.run()

output:

{
  "available_modules": " Flask 0.12 Jinja2 2.9.5 itsdangerous 0.24 Werkzeug 0.11.15 MarkupSafe 0.23 click 6.7", 
  "sys.path": [
    "/usr/share/python-wheels/lockfile-0.12.2-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/retrying-1.3.3-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/requests-2.9.1-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/wheel-0.29.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/urllib3-1.13.1-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/ipaddress-0.0.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/colorama-0.3.7-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/distlib-0.2.2-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/pyparsing-2.0.3-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/packaging-16.6-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/html5lib-0.999-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/CacheControl-0.11.5-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/six-1.10.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/chardet-2.3.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/progress-1.2-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/setuptools-20.7.0-py2.py3-none-any.whl", 
    "/usr/share/python-wheels/pip-8.1.1-py2.py3-none-any.whl", 
    "/var/www/html/flaskapp", 
    "/usr/lib/python2.7", 
    "/usr/lib/python2.7/plat-x86_64-linux-gnu", 
    "/usr/lib/python2.7/lib-tk", 
    "/usr/lib/python2.7/lib-old", 
    "/usr/lib/python2.7/lib-dynload", 
    "/usr/local/lib/python2.7/dist-packages", 
    "/usr/lib/python2.7/dist-packages"
  ]
}

So it can see the path where httplib2 lives, as well as the path to flask, but the available modules are only the Flask modules.

I'm not sure if this is a problem with my Apache configuration - I've consulted a number of how-tos and documentation, and this is the setup I've been using:

/etc/apache2/sites-enabled/000-default.conf

<VirtualHost *:80>

    WSGIDaemonProcess flaskapp threads=5 python-path=/var/www/html/flaskapp/flaskapp
    WSGIScriptAlias / /var/www/html/flaskapp/flaskapp.wsgi

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

    <Directory  /var/www/html/flaskapp>
       WSGIProcessGroup flaskapp
       WSGIApplicationGroup %{GLOBAL}
       Require all granted
       WSGIScriptReloading On
    </Directory>

</VirtualHost>  

I've looked through a number of SO posts, but most seem concerned with app not being visible to WSGI. Some posts seem close, but haven't solved my problem. I'd really appreciate any advice!

Note: I'm pretty comfortable with Python, familiar-ish with Flask, but pretty novice with Apache and WSGI. Detailed explanations/links for answers concerning the latter two topics (if appropriate) would really help.

Community
  • 1
  • 1
andrew_reece
  • 20,390
  • 3
  • 33
  • 58
  • That is a really cool piece of code you have there the flask app which tells you the installed packages and their paths, very helpful to diagnose if it's working and it renders nicely in the browser too. – cardamom Jul 03 '17 at 16:56

1 Answers1

1

You should add ~/.local/ to python-path on your Apache configuration.

WSGIDaemonProcess flaskapp threads=5 python-path=/var/www/html/flaskapp/flaskapp:/home/andrew/.local

You should also try to use virtual environments, and set python-home on WSGIDaemonProcess as the environment root.

Source: http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html

EDIT

You can also install httplib2 with sudo just like you installed the flask packages (as seen in one of your links)

  • Thanks for the prompt response. Adding `/home/andrew/.local/` as instructed didn't solve the problem. I understand virtual environments are a good idea, but shouldn't this be possible to do without using them? – andrew_reece Jan 29 '17 at 05:04
  • You could try to install httplib2 with `sudo` just like you installed the flask package. I'm sorry if I misread your question, did not see that you are not using `venv` – Ricardo Busquet Jan 29 '17 at 05:16
  • 1
    It is recommended that you do not use per user packages directory with mod_wsgi. They are bad for various reasons. Use a proper Python virtual enviormnent. If you you still want to use per user ``site-packages``, the path should have been ``/home/andrew/.local/lib/python2.7/site-packages`` and not ``/home/andrew/.local`` that you used with ``python-path`` option. – Graham Dumpleton Jan 29 '17 at 05:17
  • (I'm assuming the `sudo` from the links on your question) – Ricardo Busquet Jan 29 '17 at 05:17
  • 1
    @RicardoBusquet uninstalling `httplib2` and reinstalling with `sudo` solved the problem. Would you mind updating the main answer? Thank you!! – andrew_reece Jan 29 '17 at 05:32
  • 1
    Just went and tested with my original `python-path`, and it works. So the `~/.local/` addition wasn't necessary in my case. – andrew_reece Jan 29 '17 at 05:33