I'm having a problem with Flask wherein routes declared in imported modules are not be registered and always result in a 404. I am running the latest version Flask on Python 2.7.
I have the following directory structure:
run.py has the following code:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
import views.home
if __name__ == '__main__':
app.run()
home.py has the following code:
from run import app
#app.route('/test')
def test():
return "test"
When I run run.py the route declared in home.py (http://localhost:5000/test) always returns a 404 even though run.py imports views.home. The root view (http://localhost:5000) declared in run.py works fine.
I have written a function that prints out all the registered routes and /test is not in there (get a list of all routes defined in the app).
Any idea why?
I have discovered that switching the import statement in run.py from
import views.home
to
from views.home import *
makes everything work, which gave me the clue as to why the modules are not being registered using import views.home.
Basically, when run.py is run as a script it is given the name __main__ and this is the name given to the module in sys.modules (Importing modules: __main__ vs import as module)
Then when I import app from run.py in views.home.py a new instance of run.py is registered in sys.modules with the name run. As this point, the reference to app in run.py and views.home.py are two different references hence the routes not being registered.
The solution was to move the creation of the app variable out of run.py and in to a separate python file (I called it web_app.py) that is imported into run.py. This guarantees that the Flask app variable declared inside web_app.py is the always referenced correctly wherever web_app.py is imported.
So run.py now looks like this:
from web_app import app
if __name__ == '__main__':
app.run()
and web_app.py looks like this:
from flask import Flask
app = Flask(__name__)
import view.home
You can do it by reorganizing your code as it is described here Larger Applications, but it is more recommended to divide them into smaller groups where each group is implemented with the help of a blueprint. For a gentle introduction into this topic refer to the Modular Applications with Blueprints chapter of the documentation.
Modular Applications with Blueprints
Related
I have the following folder structure:
In the application.py file I am using a factory method create_app():
# application.py
def create_app():
flask_app = Flask(__name__)
return flask_app
app = create_app()
# --- Import Routes ---
from src.routes import *
if __name__ == "__main__":
app.run()
In the test folder I have the following code
# /tests/test.py
from application import create_app
def test_root_route():
flask_app = create_app()
with flask_app.test_client() as test_client:
response = test_client.get('/')
assert response.status_code == 200
Now I get the following error when running the test:
from application import create_app
ModuleNotFoundError: No module named 'application'
Why can't I import the method from the application.py file?
Unfortunately I can't change the folder structure as the application.py needs to be in root so it can be run by our server.
Please share folder structure properly , looking at it currently seems like while running tests.py , the application.py file is in the directory above the current one .
Also you can try to make a test.py where apllication.py is located. Then import the tests you've written in test directory.
try using from .application import with and __init__.py file in the root file
Python has a lot of problems with sibling imports
I am trying to import module from file in my parent directory but is not working
Here is how my directory looks like :
Here is how my main.py file looks like :
import sys
path_modules="./Utils"
sys.path.append(path_modules)
from functools import lru_cache
from flask import Flask, render_template, request
import Utils.HardSoftClassifier as cl
import Utils.prediction_utils as ut
import Utils.DataPrepper_reg as prep
app = Flask(__name__)
#app.route('/')
#app.route('/index')
def index():
return render_template('index.html')
#app.route('/viz')
def viz():
return render_template('viz.html')
if __name__=="__main__":
# import os
# os.system("start microsoft-edge:http:\\localhost:5000/")
app.run(debug=True)
Here is my flaks output :
In order to make a package importable, it must have an (optionally empty) __init__.py file in its root. So first create an empty __init__.py file in the Utils directory.
Furthermore, you don't have to alter the import path, since you start the Flask app from the Clean_code, the simple relative importing will work. So the first three line can be removed from main.py.
A brief introduction to the directory structure is as follows:
__init__.py contain the application factory.
page.py
from app import app
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
app.py
from flaskr import create_app
app = create_app()
if __name__ == '__main__':
app.run()
When I start the server and go to the '/hello', it says 404.
What's the problem?
Here is a short solution which should run.
page.py
from flaskr import app
#app.route('/hello')
def hello():
return 'Hello'
__index__.py
from flask import Flask
app = Flask(__name__)
from flaskr import page
app.py
from flaskr import app
To run this you just need to define a Environment Variable on the Commandline like this:
export FLASK_APP=microblog.py
And then run it with
flask run
The way you have structured your code is not right. That's the reason you are not able to access your "/hello" API.
Let's assume that you run the app.py file. In this case, you haven't imported page.py right? So, how will the app.py know that there is a route defined in page.py?
Alternatively, let's assume you run page.py. In this case, when you do an "from app import app" , the main definition does not get executed. Here too, the route will now be present, but the app will not be run, thereby you will be unable to access your API.
The simplest solution would be to combine the contents of app.py and page.py into a single file.
Initial note: I know there are many of these type posts for python but I've tried many of the solutions and they have not worked for me.
File structure:
/nickdima
__init__.py
/test_pong
__init__.py
pong.py
/nickdima/__init__.py:
from flask_socketio import Socketio
socker = SocketIO()
from test_pong import pong
def create_app():
app = Flask(__name__)
socker.init_app(app)
return app
/nickdima/test_pong/pong.py
from __main__ import socker
#socker.on('connect')
def handle_connect():
print('connected')
When I run this code on Heroku I get the error:
from __main__ import socker
ImportError: cannot import name 'socker'
I'm fairly certain this is related to a circular import but I cannot solve it.
I've tried putting: from test_pong import pong
inside the create_app() function to "delay the import" locally but to no avail and I get the same error cannot import name 'socker'
Ok, so after further inspection here's what I suggest:
/nickdima
__init__.py
socker.py
/test_pong
__init__.py
pong.py
/nickdima/socker.py
from flask_socketio import Socketio
socker = SocketIO()
/nickdima/__init__.py:
from nickidima.socker import socker
from nickidima.test_pong import pong
def create_app():
app = Flask(__name__)
socker.init_app(app)
return app
/nickdima/test_pong/pong.py
from nickidima.socker import socker
#socker.on('connect')
def handle_connect():
print('connected')
This way you no longer have circular dependencies!
Imports are relative to the root directory where nickidima is placed. I'm not sure how Heroku works with this kind of importing (actually I've never used Heroku) but I hope you get the idea and will be able to tweak it to your needs.
The most important lesson: circular dependencies are almost always a sign of a bad design and almost always can be replaced with non-circular dependencies. And when they can: do it.
Side note: I'm following your naming convention (socker?) but seriously, you should fix it. :)
I can't get it to work to use one module that creates the Flask application object and runs it, and one module that implements the views (routes and errorhandlers). The modules are not contained in a Python package.
app.py
from flask import Flask
app = Flask('graphlog')
import config
import views
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
views.py
from app import app
#app.route('/')
def index():
return 'Hello!'
config.py
host = 'localhost'
port = 8080
debug = True
I always get Flask's default "404 Not Found" page. If I move the contents of view.py to app.py however, it works. What's the problem here?
You have four modules here:
__main__, the main script, the file you gave to the Python command to run.
config, loaded from the config.py file.
views, loaded from the views.py file.
app, loaded from app.py when you use import app.
Note that the latter is separate from the first! The initial script is not loaded as app and Python sees it as different. You have two Flask objects, one referenced as __main__.app, the other as app.app.
Create a separate file to be the main entry point for your script; say run.py:
from app import app
import config
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
and remove the import config line from app.py, as well as the last two lines.
Alternatively (but much uglier), use from __main__ import app in views.py.