How to get config params in another module in flask python? - python

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. ;-)

Related

Trying to reuse code across multiple Flask servers, stuck on importing with errors "ModuleNotFoundError" or "ImportError"

My goal is to import code into three separate Flask servers. It's not going well. I am on python 3.10.4. I have read perhaps 10 different posts that say things like "put a __init__.py file in your folders" which I have done.
For context I'm not exactly new to Python but I've never learned the importing/module system properly.
I have three Flask servers that run scraping operations on different (but similar) websites. I need them to be separate for various reasons. Anyway, all three need to run the same procedure of getting an IP for a proxy from my proxy provider. For this I have some code:
# we don't need the details here so I snip it to save space
def get_proxy_ip(choice):
r = requests.get(download_list, headers={"Authorization": "Token " + token})
selected_proxy_ip = r.json()["results"][choice]["proxy_address"]
selected_proxy_port = r.json()["results"][choice]["port"]
print(selected_proxy_ip)
return selected_proxy_ip, selected_proxy_port
I want to use this function across all 3 of my Flask servers. Here are some various ways I've tried to import the code into one of the Flask servers:
scrapers/rentCanada/app.py
import requests
from flask import Flask, request, make_response
print("cats")
app = Flask(__name__)
print(__name__, __package__)
# from ..shared.ipgetter import get_proxy_ip
# from ..shared.checker import check_public_ip
# from scrapers.shared.ipgetter import get_proxy_ip
# from scrapers.shared.checker import check_public_ip
import shared.ipgetter as ipgetter
import shared.checker as checker
None of them work.
import shared.ipgetter as ipgetter yields:
cats
__main__ None
Traceback (most recent call last):
File "/home/rlm/Code/canadaAps/scrapers/rentCanada/app.py", line 10, in <module>
import shared.ipgetter as ipgetter
ModuleNotFoundError: No module named 'shared'
ModuleNotFoundError: No module named 'scrapers' yields: ModuleNotFoundError: No module named 'scrapers'
from ..shared.ipgetter import get_proxy_ip yields: ImportError: attempted relative import with no known parent package
At this point you need to see my folder structure.
/scrapers
..__init__.py
..setup.py
../rentCanada
.....__init__.py
.....app.py
../rentFaster
.....__init__.py
.....app.py
../rentSeeker
.....__init__.py
.....app.py
../shared
.....__init__.py
.....ipgetter.py
.....checker.py
I need to be able to use any of the app.py files as entry points.
I also tried setup.py with this:
from setuptools import setup, find_packages
setup(
name = 'tools',
packages = find_packages(),
)
followed by python setup.py install but that didn't make a "tools" import available in app.py like I wanted.
As a final note I suspect someone will tell me to use a blueprint. To me those look like a tool I'd use if I was adding a route. I'm not sure they're right for a simple function, but maybe I'm wrong.
My solution for now is to run Flask with python rentCanada/app.py from the /scrapers folder and use this code
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent)) # necessary so util folder is available
import requests
from flask import Flask, request, make_response
print("cats")
app = Flask(__name__)
print(__name__, __package__)
from util.ipgetter import get_proxy_ip
from util.checker import check_public_ip
So the program appends the app.py file folder's parent folder to the path. That makes the util folder (which used to be shared but had a naming conflict) available within the app.py file.

flask run giving me ModuleNotFoundError

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.

How to reference create_app from different sub-domain?

The relevant part of my app structure looks like the following:
hp/
|
|---app/
|---admin/
|---auth/
|---errors/
|---main/
|---__init__.py
|---email.py
|---models.py
|---search.py
|---config.py
|---quiz.py
I want to create a scripts/ domain in either hp/ or app/. In those scripts I need to be able to reference config values. I'm using dotenv to do that. In order to use dotenv, I need app to be available so that I can call app.config['CONFIG_NAME'].
Here's more or less what I'm trying to do:
import requests
from app import app
access_key = app.config['ACCESS_KEY']
secret_key = app.config['SECRET_KEY']
data = requests.get(f'https://api.foo.com/search?client_id={access_key}&page=1&query=foo').json()
If I try from app import app, as I have above, I get a ModuleNotFoundError: No module named 'app' error. If I try from .. import app I get a ValueError: attempted relative import beyond top-level package error.
Any guidance/advice is greatly appreciated!
I ended up solving this by changing the sys.path.
I added the following:
import sys
import os
import inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
appdir = os.path.dirname(currentdir)
hpdir = os.path.dirname(appdir)
sys.path.insert(0, hpdir)
from app import create_app
app = create_app()
After that I was able to successfully call app.config

Python 2.7.3 Flask ImportError: No module named

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.

"ImportError: cannot import name mail" in Flask

I have built is a simple web app with Flask and Python, which I intend to upload to Heroku.
When starting my app locally, with the following script:
#!venv/bin/python
from app import app
app.run(debug = True)
I get this error message:
Traceback (most recent call last):
File "./run.py", line 2, in <module>
from app import app, mail
File "/home/ricardo/personalSite/app/__init__.py", line 3, in <module>
from app import index
File "/home/ricardo/personalSite/app/index.py", line 6, in <module>
from emails import send_email
File "/home/ricardo/personalSite/app/emails.py", line 2, in <module>
from app import app, mail
ImportError: cannot import name mail
So, it cannot import mail.
Inside the app directory I have this __init__.py, here is were I create the Mail object that is ginving me trouble to import:
from flask import Flask
app = Flask(__name__)
from app import index
from flask.ext.mail import Mail
mail = Mail(app)
And this is the file emails.py where I call the send_mail function:
from flask.ext.mail import Message
from app import app, mail
from flask import render_template
from config import ADMINS
from decorators import async
So, according to the error message, the error is in this file, in the from app import app, mail.
What is the problem? Why can't it import mail?
Update:
This is my directory listing:
persSite\
venv\
<virtual environment files>
app\
static\
templates\
__init__.py
index.py
emails.py
decorators.oy
tmp\
run.py
You have a circular dependency. You have to realize what Python is doing when it imports a file.
Whenever Python imports a file, Python looks to see if the file has already started being imported before. Thus, if module A imports module B which imports module A, then Python will do the following:
Start running module A.
When module A tries to import module B, temporarily stop running module A, and start running module B.
When module B then tries to import module A, then Python will NOT continue running module A to completion; instead, module B will only be able to import from module A the attributes that were already defined there before module B started running.
Here is app/__init__.py, which is the first file to be imported.
from flask import Flask
app = Flask(__name__)
from app import index # <-- See note below.
from flask.ext.mail import Mail
mail = Mail(app)
When this file is imported, it is just Python running the script. Any global attribute created becomes part of the attributes of the module. So, by the time you hit the third line, the attributes 'Flask' and 'app' have been defined. However, when you hit the third line, Python begins trying to import index from app. So, it starts running the app/index.py file.
This, of course, looks like the following:
from flask.ext.mail import Message
from app import app, mail # <-- Error here
from flask import render_template
from config import ADMINS
from decorators import async
Remember, when this Python file is being imported, you have thus far only defined Flask and app in the app module. Therefore, trying to import mail will not work.
So, you need to rearrange your code so that if app.index relies on an attribute in app, that app defines that attribute before attempting to import app.index.
This is probably the problem:
from app import app, mail
In the file 'app/emails.py' the import is from the current module, not a nested app module. Try:
from . import app, mail
If it doesn't work, you should update your question with a more detailed directory listing.

Categories

Resources