I'm relatively new to python and am trying to build a flask server. What I would like to do is have a package called "endpoints" that has a list of modules where each module defines a subset of application routes. When I make a file called server.py with the following code this works like so
import os
from flask import Flask
app = Flask(__name__)
from endpoint import *
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)
Right now there's only one endpoint module called hello.py and it looks like this
from __main__ import app
# a simple page that says hello
# #app.route defines the url off of the BASE url e.g. www.appname.com/api +
# #app.route
# in dev this will be literally http://localhost:5000/hello
#app.route('/hello')
def hello():
return 'Hello, World!'
So... the above works when I run python server.py, the issue happens when I try to run the app using flask.
Instead of server.py it just calls __init__.py which looks like this
import os
from flask import Flask
# create and configure the app
# instance_relative_config states that the
# config files are relative to the instance folder
app = Flask(__name__, instance_relative_config=True)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
from endpoint import *
When I run flask run in terminal I get ModuleNotFoundError: No module named 'endpoint'
but again if I change the code so it looks like the following below, then flask run works.
import os
from flask import Flask
# create and configure the app
# instance_relative_config states that the
# config files are relative to the instance folder
app = Flask(__name__, instance_relative_config=True)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
# #app.route defines the url off of the BASE url e.g. www.appname.com/api +
# #app.route
# in dev this will be literally http://localhost:5000/hello
#app.route('/hello')
def hello():
return 'Hello, World!'
I'm pretty sure this is happening because I don't fully understand how imports work...
So, how do I set up __init__.py so that it imports all the modules from the "endpoint" package and works when I call flask run?
When you use a __init__.py file, which you should, Python treats the directory as a package.
This means, you have to import from the package, and not directly from the module.
Also, usually you do not put much or any code in a __init__.py file.
Your directory structure could look like this, where stack is the name of the package I use.
stack/
├── endpoint.py
├── __init__.py
└── main.py
You __init__.py file is empty.
main.py
import os
from flask import Flask
# create and configure the app
# instance_relative_config states that the
# config files are relative to the instance folder
app = Flask(__name__, instance_relative_config=True)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
from stack.endpoint import *
endpoint
from stack.main import app
# a simple page that says hello
# #app.route defines the url off of the BASE url e.g. www.appname.com/api +
# #app.route
# in dev this will be literally http://localhost:5000/hello
#app.route('/hello')
def hello():
return 'Hello, World!'
You can then run your app...
export FLASK_APP=main.py
# followed by a...
flask run
This all said, when I create a new Flask app, I usually only use one file, this makes initial development easier, and only split into modules when the app really grows bigger.
Also, for separating views or let's call it sub packages, Flask offers so called Blue prints. This is nothing you have to worry about right now, but comes especially handy when trying to split the app into sub applications.
Related
I am a Flask beginner, please excuse me if the answer to my question is obvious.
I have been working on a project using an OVH server. I have been using this tutorial to set up a first "Hello world": https://docs.ovh.com/gb/en/web-power/python-install-flask/
Here is the structure of my project :
www/
venv/
myapp.py
At this point, everything is working fine. When I connect to my website, it shows a good "Hello, world !" as expected.
However I now want to add a template to my page, I have therefore added a few lines :
this_file = "venv/bin/activate_this.py"
exec(open(this_file).read(), {'__file__': this_file})
from flask import Flask, render_template
application = Flask(__name__)
#application.route('/')
#application.route('/index')
def index():
return render_template('index.html')
I have imported render_template and changed from "return 'Hello'" to "return render_template('index.html')".
Unfortunately, my website now displays "Incomplete response received from application". I have tried these 2 structures :
www/
venv/
myapp.py
templates/
index.html
and :
www/
templates/
index.html
venv/
myapp.py
But it doesn't change anything... Does any know how to return a template?
instead of starting the venv up from within the program with
this_file = "venv/bin/activate_this.py"
exec(open(this_file).read(), {'__file__': this_file})
(works only on mac/Linux) you might want to do that in the terminal instead,
as
venv/bin/activate
source: https://uoa-eresearch.github.io/eresearch-cookbook/recipe/2014/11/26/python-virtual-env/
then, to run your file, you can add this:
from flask import Flask, render_template
application = Flask(__name__)
#application.route('/')
#application.route('/index')
def index():
return render_template('index.html')
if __name__ == '__main__':
application.run(debug=True)
the last lines are good habit for projects like these, debugger on is extremely useful. Your structure is fine. I understand why you might want to add the first few lines, I am working on a venv flask app too. However, I tried implementing the windows version of those lines, which did not work... even if that works fine for you, please consider adding
if __name__ == '__main__':
application.run(debug=True)
either way.
The Following is my code hierarchy.
I am trying to create a package for my project, "UIGenerator" but it is giving me following error.
traceback (most recent call last):
File "run.py", line 1, in <module>
from UIGenerator import app
File "/Users/______/Desktop/UIGenerator/UIGenerator/__init__.py", line 2, in <module>
from site.routes import site
ModuleNotFoundError: No module named 'site.routes'; 'site' is not a package
Here is the code for run.py =>
from UIGenerator import app
#app.route('/')
def test_connection():
return "<h1>Connected<h1>"
if __name__ == '__main__':
app.run(debug=True)
There is nothing in site =>__init__.py file and in site=>routes.py, I have some sample code to test-
from flask import Blueprint
site = Blueprint('site', __name__)
#site.route('/site')
def site():
return "this is test for site package"
The following is my code for the UIGenerator's init.py file =>
from flask import Flask
from site.routes import site
def getApp():
app = Flask(__name__)
app.register_blueprint(site)
return app
app = getApp()
Can anyone give me any clue, please.
One way to fix this is to build a Python package with you files, like outlined here. This will be better in the long run if you want to scale this project up, and will allow you to declare things in init
That being said, I think you can get your setup working by moving this chunk of code
def getApp():
app = Flask(__name__)
app.register_blueprint(site)
return app
app = getApp()
to the run.py file for the time being.
So, here is what I found out from a different post. In my site=>routes, I declared a global blueprint with the name, site and later I created a site() function which somehow masked my site blueprint. If I just renamed the site method name, it works.
This is my project structure:
myproject
myproject
__init__.py
static
templates
views
__init.py__
home.py
venv
myproject.wsgi
requirements.txt
setup.py
This is my __init__.py:
from flask import Flask, request, Response, render_template
from myproject.views import home
app = Flask(__name__, static_folder="static", static_url_path='/static')
test_string = "Hello World!"
app.register_blueprint(home.home)
And this is my views/home.py:
from flask import Flask, request, Response, Blueprint
import json
import requests
from myproject import test_string
home = Blueprint('home', __name__)
#home.route('/', methods=['GET'])
def test():
return(test_string)
When I visit the page, I get an error ImportError: cannot import name test_string. The Python import system is really confusing and I am not sure what I am doing wrong here, but I suspect this is a circular import issue.
How do I solve this?
Try to move, in __init__.py, the line from myproject.views import home after the line test_string = "Hello World!".
This way Python will be find the test_string name.
To understand circular imports you have to "think like the interpreter", when you execute __init__.py the interpreter will:
execute line 1 of __init__.py
execute all the code that this line implies (importing stuff from flask)
execute line 2 of __init__.py
execute line 1 of views/home.py (importing only Blueprint from flask, for it's the onnly non-already-imported thing)
execute lines 2+3 of views/home.py (import json and requests)
execute line 4 of views/home.py
go back to what he executed in __init__.py and search for the name test_string
here it raises an error, because what he executed do not comprehend test_string. If you move the import after the execution of test_string = "Hello World!" the interpreter will find this name in the namespace.
This is commonly recognized as bad design though, IMHO the best place to store test_string would be a config.py file, in which no imports from other project modules are performed, avoiding circulat imports.
In my main.py have the below code:
app.config.from_object('config.DevelopmentConfig')
In another module I used import main and then used main.app.config['KEY'] to get a parameter, but Python interpreter says that it couldn't load the module in main.py because of the import part. How can I access config parameters in another module in Flask?
Your structure is not really clear but by what I can get, import your configuration object and just pass it to app.config.from_object():
from flask import Flask
from <path_to_config_module>.config import DevelopmentConfig
app = Flask('Project')
app.config.from_object(DevelopmentConfig)
if __name__ == "__main__":
application.run(host="0.0.0.0")
if your your config module is in the same directory where your application module is, you can just use :
from .config import DevelopmentConfig
The solution was to put app initialization in another file (e.g: myapp_init_file.py) in the root:
from flask import Flask
app = Flask(__name__)
# Change this on production environment to: config.ProductionConfig
app.config.from_object('config.DevelopmentConfig')
Now to access config parameters I just need to import this module in different files:
from myapp_init_file import app
Now I have access to my config parameters as below:
app.config['url']
The problem was that I had an import loop an could not run my python app. With this solution everything works like a charm. ;-)
I have a Flask application with this error:
ImportError: No module named annotaria, referer: http://ltw1413.web.cs.unibo.it/
So, my root in web server is:
/home/web/ltw1413/html
Inside html folder I have:
One folder named "annotaria
One file .wsgi named "wsgi.wsgi"
My file .wsgi is:
import sys
sys.path.insert(0, '/home/web/ltw1413/html')
from annotaria import app as application
Inside my folder "annotaria" I have:
"Static" folder : inside stylesheet and js
"Templates" folder : inside html
"run.py" : file python where I have my application
run.py is this:
from pydoc import html
from annotaria import app
from flask import Flask, render_template, redirect, request
import json
import urllib2
import urlparse
import re
import string
import os
from SPARQLWrapper import SPARQLWrapper, JSON
from rdflib import Graph, BNode, Literal, Namespace
from time import strftime
import urllib2
import BeautifulSoup
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/index.html')
def reloader():
return render_template('index.html')
# other app.route()...
if __name__ == '__main__':
app.run(debug=True)
How can I find a solution? Where is my error?
Lots of errors here...
annotaria is not found on path (that is why it says... well.. exactly that).
In your code you also redefine app: you import it from annotaria and then redefine it in app = Flask(...
Others mentioned individual errors, but it would be helpful to understand the big picture. First of all, let's assume the following structure:
/home/web/ltw1413/html
- wsgi.wsgi
- annotaria/
- __init.py__
- run.py
- static/
- templates
Like Klaus mentioned, you need __init__.py to tell Python that annotaria is a valid package. But then your wsgi.wsgi file needs to import the app from the run module:
from annotaria.run import app as application
You also need to remove this unnecessary import from run.py, since you instantiate a new application:
from annotaria import app
Because there is no application to import, you instantiate a new Flask application.
Finally, make sure that the app runs manually before you start deploying it.