I had only one big file serving my application app.py, but now, I decided to split into several files to separate the code. After this separation, the WSGI doesn't start anymore with an error related to import a function.
ImportError: cannot import name month_string_to_number
The code now is divided into 3 main files: app.py, views.py and models.py. Here you have some code, as well as the Apache and WSGI configuration.
app.py
import sqlite3
import json
import os
import csv
import codecs
from flask import Flask, jsonify, g, request, abort, render_template, redirect, url_for, flash
from flask_sqlalchemy import Model, SQLAlchemy
from sqlalchemy import text, and_
from datetime import datetime, timedelta
from werkzeug import secure_filename
from flask_login import LoginManager
app = Flask(__name__)
login = LoginManager(app)
login.login_view = 'login'
app.secret_key = 'certificates-management'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///certificates.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
dir_path = os.path.dirname(os.path.realpath(__file__))
db = SQLAlchemy(app)
from views import *
def month_string_to_number(string):
m = {
'jan': '1',
'feb': '2',
'mar': '3',
'apr': '4',
'may': '5',
'jun': '6',
'jul': '7',
'aug': '8',
'sep': '9',
'oct': '10',
'nov': '11',
'dec': '12'
}
s = string.strip()[:3].lower()
try:
out = m[s]
return out
except:
raise ValueError('Not a month')
if __name__ == '__main__':
app.run(debug=True)
views.py
import sqlite3
import json
import os
import csv
import codecs
from flask import Flask, jsonify, g, request, abort, render_template, redirect, url_for, flash
from flask_sqlalchemy import Model, SQLAlchemy
from models import Worker, Certificates, Logs, User, return_workers, insert_db, create_log_entry
from sqlalchemy import text, and_
from datetime import datetime, timedelta
from werkzeug import secure_filename
from app import app, db, month_string_to_number
from flask_login import current_user, login_user, logout_user, login_required
from urlparse import urlparse
@app.errorhandler(404)
def not_found(error):
return render_template('error.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
if current_user.is_authenticated:
return redirect(url_for('index'))
user_name = request.form['username']
user_password = request.form['password']
remember_me = request.form.get('remember_me', False)
user = User.query.filter_by(username=user_name).first()
dir(user)
if user is None or not user.check_password(user_password):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=remember_me)
create_log_entry(current_user.name, "Logged in to the system", "Login")
flash("Login successfull", 'success')
return redirect(url_for('index'))
return render_template('login.html')
@app.route('/logout')
def logout():
create_log_entry(current_user.name, "Logged out from the system", "Logout")
logout_user()
flash("Logged out successfully", 'success')
return redirect(url_for('index'))
models.py
from app import app, db, login
import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
username = db.Column(db.String(255), nullable=False, unique=True)
password_hash = db.Column(db.String(255), nullable=False)
def __init__(self, username, password):
self.username = username
self.password_hash = password
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
The WSGI code is this:
import sys
sys.path.append("/var/www/certs-management")
from app import app as application
And the Apache config:
<virtualhost *:80>
ServerName myserver.example
WSGIDaemonProcess certs-management user=apache group=apache threads=5 home=/var/www/certs-management/
WSGIScriptAlias / /var/www/certs-management/cert-management.wsgi
Alias /static /var/www/certs-management/static/
<Directory "/var/www/certs-management/static/">
Order allow,deny
Allow from all
</Directory>
Alias /templates /var/www/certs-management/templates/
<Directory "/var/www/certs-management/templates/">
Order allow,deny
Allow from all
</Directory>
<directory /var/www/certs-management>
WSGIProcessGroup certs-management
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Order deny,allow
Allow from all
</directory>
</virtualhost>
The error message is the following:
[Wed Jan 31 18:59:48.397516 2018] [mpm_prefork:notice] [pid 5634] AH00171: Graceful restart requested, doing restart
[Wed Jan 31 18:59:48.546219 2018] [auth_digest:notice] [pid 5634] AH01757: generating secret for digest authentication ...
[Wed Jan 31 18:59:48.546904 2018] [lbmethod_heartbeat:notice] [pid 5634] AH02282: No slotmem from mod_heartmonitor
[Wed Jan 31 18:59:48.547518 2018] [mpm_prefork:notice] [pid 5634] AH00163: Apache/2.4.6 (Red Hat Enterprise Linux) mod_wsgi/3.4 Python/2.7.5 configured -- resuming normal operations
[Wed Jan 31 18:59:48.547538 2018] [core:notice] [pid 5634] AH00094: Command line: '/usr/sbin/httpd'
[Wed Jan 31 18:59:52.011929 2018] [:error] [pid 3881] [remote :176] mod_wsgi (pid=3881): Target WSGI script '/var/www/certs-management/cert-management.wsgi' cannot be loaded as Python module.
[Wed Jan 31 18:59:52.011985 2018] [:error] [pid 3881] [remote :176] mod_wsgi (pid=3881): Exception occurred processing WSGI script '/var/www/certs-management/cert-management.wsgi'.
[Wed Jan 31 18:59:52.012015 2018] [:error] [pid 3881] [remote :176] Traceback (most recent call last):
[Wed Jan 31 18:59:52.012033 2018] [:error] [pid 3881] [remote :176] File "/var/www/certs-management/cert-management.wsgi", line 3, in <module>
[Wed Jan 31 18:59:52.012098 2018] [:error] [pid 3881] [remote :176] from app import app as application
[Wed Jan 31 18:59:52.012111 2018] [:error] [pid 3881] [remote :176] File "/var/www/certs-management/app.py", line 26, in <module>
[Wed Jan 31 18:59:52.012158 2018] [:error] [pid 3881] [remote :176] from views import *
[Wed Jan 31 18:59:52.012169 2018] [:error] [pid 3881] [remote :176] File "/var/www/certs-management/views.py", line 12, in <module>
[Wed Jan 31 18:59:52.012320 2018] [:error] [pid 3881] [remote :176] from app import app, db, month_string_to_number
[Wed Jan 31 18:59:52.012347 2018] [:error] [pid 3881] [remote :176] ImportError: cannot import name month_string_to_number
I really have no idea why it's happening. To configure this app, I just followed the documentation at: http://flask.pocoo.org/docs/0.12/deploying/mod_wsgi/
PS: The server name is not right and the information about IP of remote host was also removed - which I am sure are not relevant to the issue.
Thank you.