0
votes

I've recently been struggling to deploy my Flask app to AWS ElasticBeanstalk. I'm fairly new to web projects and AWS so every day is a struggle. Every once in a while I deploy my project to EB (I have been able to solve problems in the past) but since I restructured my app from a monolithic application.py to a more structured approach, I've been struggling. The deployment itself has succeeded but I'm faced with a 500 error. The log says:

[Wed Apr 19 00:11:57.895790 2017] [:error]  mod_wsgi (pid=15947): Target WSGI script '/opt/python/current/app/app/members/views.py' cannot be loaded as Python module.
[Wed Apr 19 00:11:57.895846 2017] [:error]  mod_wsgi (pid=15947): Exception occurred processing WSGI script '/opt/python/current/app/app/members/views.py'.
[Wed Apr 19 00:11:57.895865 2017] [:error]  Traceback (most recent call last):
[Wed Apr 19 00:11:57.895881 2017] [:error]    File "/opt/python/current/app/app/members/views.py", line 14, in 
[Wed Apr 19 00:11:57.895903 2017] [:error]      @application.route('/')
[Wed Apr 19 00:11:57.895909 2017] [:error]   File "/opt/python/run/venv/lib/python2.7/site-packages/flask/app.py", line 1080, in decorator
[Wed Apr 19 00:11:57.895921 2017] [:error]      self.add_url_rule(rule, endpoint, f, **options)
[Wed Apr 19 00:11:57.895935 2017] [:error]   File "/opt/python/run/venv/lib/python2.7/site-packages/flask/app.py", line 64, in wrapper_func
[Wed Apr 19 00:11:57.895944 2017] [:error]      return f(self, *args, **kwargs)
[Wed Apr 19 00:11:57.895949 2017] [:error]   File "/opt/python/run/venv/lib/python2.7/site-packages/flask/app.py", line 1051, in add_url_rule
[Wed Apr 19 00:11:57.895956 2017] [:error]     'existing endpoint function: %s' % endpoint)
[Wed Apr 19 00:11:57.895969 2017] [:error]  AssertionError: View function mapping is overwriting an existing endpoint function: index

My apps structure is:

myApp/
   runServer.py
   requirements.txt
   app/
      __init__.py
      config.py
      static/
      members/
         __init__.py
         views.py
         models.py
      templates/

My .ebextensions/<env-name>.config contains:

option_settings:
  "aws:elasticbeanstalk:container:python":
    WSGIPath: app/members/views.py

Lastly, my views.py file contains all my url routings. I have made sure all of the function names are the same.

Does anybody know what kind of problem/solution I'm looking at? Is there any more info I can provide to help?

Thanks!

Edit: Changing my def index() function in views.py to def newFunctionForTesting() yields AssertionError: View function mapping is overwriting an existing endpoint function: newFunctionForTesting

Edit 2: It may be similar to this one, but in that case the proposed solution was to write everything in a single file, which isn't the approach I was looking for... Maybe Blueprints could work better...

Edit 3: Here's what my app looks like.

app\__init__.py


    from flask import Flask, flash, request
    from urlparse import urlparse, urljoin
    from urllib2 import urlopen
    from flask_user import SQLAlchemyAdapter, UserManager, current_user
    import os
    from apscheduler.schedulers.background import BackgroundScheduler
    import pandas as pd
    from app.members.models import db, User, AcademicData, Role, UserRoles, Query
    from passlib.hash import bcrypt
    import datetime
    import json

    # Initializes application
    application = Flask(__name__)
    application.config.from_object("app.config.Config")

    # Initializes db
    db.init_app(application)

    # Registers user model with db
    with application.app_context():
        db.create_all() # Creates tables defined
        db_adapter = SQLAlchemyAdapter(db, User)        # Register the User model

    @application.before_first_request
    def initialize():
        scheduler = BackgroundScheduler()
        scheduler.start()
        scheduler.add_job(updateData, trigger = "interval", days = 1)



    def updateData():
        ...


    @application.context_processor
    def injectFunction():
        def getDataTable(id):
            ...

    import members.views

    # Initialize flask-user
    user_manager = UserManager(db_adapter, application,register_view_function = members.views.protected_register)

app\members\views.py


    from flask import redirect, url_for, render_template, request
    from flask_user import login_required, roles_required, views as user_views
    from app import application, SITE_ROOT
    import json
    import os
    import pandas as pd

    @application.route('/')
    def index():
        """
        Index view. Currently the dashboard.
        :return: 
        """
        return redirect(url_for('dashboard'))

    @application.route('/dashboard')
    @login_required
    def dashboard():
        ...
        return render_template('dashboard.html')

    @application.route('/table')
    @login_required
    def table():
        return render_template('table.html')

    @application.errorhandler(404)
    def not_found(error):
         return render_template('404.html')

    @application.errorhandler(500)
    @application.errorhandler(503)
    def server_error(error):
        return render_template('503.html')

    @roles_required('admin')
    def protected_register():
        return user_views.register()

1
The error says AssertionError: View function mapping is overwriting an existing endpoint function: index - are you importing your app in views.py from anywhere, and (either way) are you defining another route on a function named index anywhere (regardless of whether the URL is different, what's the name of the function).Sean Vieira
There is no route outside of views.py (at least not defined by me) and no other functions named index in the project. I do from app import application for the routing and import app. This last import is a temporary measure to access a shared global variable. This seems like a terrible pattern and will be changed in time. I should also mention that the application works fine locally with the built-in server.Gabriel Siqueira
Thank you for the input and your work on Flask. I will work on the example and include one once I have it. I have checked all view functions and routes and there is no conflict. This doesn't happen when ran with the built-in server from Flask. I've made that mistake before (which gave me an error with the built-in server) but at least now it's not that kind of accidentally naming two view functions the same. Maybe this has something to do with including views.py at the bottom of my __init.py__ and including app in views.py?Gabriel Siqueira
Changing my def index() function in views.py to def newFunctionForTesting() yields AssertionError: View function mapping is overwriting an existing endpoint function: newFunctionForTesting. I also removed the import app from my views.py just in case.Gabriel Siqueira

1 Answers

0
votes

I was following this example to set my WSGIPath, but since @davidism pointed it out, I tried a different approach and it worked. I created a app.wsgi file that basically just imports my application object and set WSGIPath: app/app.wsgi in my .ebextensions/<env-name>.config. The application now deploys and launches successfully through Elastic Beanstalk. My static resources stopped working but I had to update the mapping of the static folder under Configuration > Software Configuration > Static Files in the Elastic Beanstalk console.

Thanks!