Flask Blueprint AttributeError: 'module' object has no attribute 'name' error - python

My API is being built to allow developers to extend it's functionality. My plan is to do this by providing an "extensions" directory where they can drop in Blueprints and they will be dynamically loaded. This is the code I am utilizing to import (modifed from this tutorial)
from flask import Flask
import pkgutil
import sys
app = Flask(__name__)
EXTENSIONS_DIR = "extensions"
modules = pkgutil.iter_modules(path=[EXTENSIONS_DIR])
for loader, mod_name, ispkg in modules:
if mod_name not in sys.modules:
# It imports fine
loaded_mod = __import__(EXTENSIONS_DIR+"."+mod_name+"."+mod_name, fromlist=[mod_name])
# It does not register
app.register_blueprint(loaded_mod)
This is the directory layout of my project. The extensions directory is where developers drop in their expanded functionality.
/root
/extensions
/extension1
__init__.py
extension1.py
/extension2
__init__.py
extension2.py
simple_example.py
The problem is that I get this error and am not sure what it is telling me.
>python simple_example.py
Traceback (most recent call last):
File "simple_example.py", line 14, in <module>
app.register_blueprint(loaded_mod)
File "C:\Python27\lib\site-packages\flask\app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Python27\lib\site-packages\flask\app.py", line 880, in register_blueprint
if blueprint.name in self.blueprints:
AttributeError: 'module' object has no attribute 'name'
A simple extension looks like this
from flask import Blueprint
extension1 = Blueprint('extension1', __name__)
#extension1.route("/my_route")
def treasure_list():
return "list of objects"
How do I solve the AttributeError in a way that allows my app.register_blueprint call to succeed?

You are trying to register the module and not the contained Blueprint object.
You'll need to introspect the module to find Blueprint instances instead:
if mod_name not in sys.modules:
loaded_mod = __import__(EXTENSIONS_DIR+"."+mod_name+"."+mod_name, fromlist=[mod_name])
for obj in vars(loaded_mod).values():
if isinstance(obj, Blueprint):
app.register_blueprint(obj)

When I got this error my code looked like this:
from blueprints import api
...
app.register_blueprint(api)
I fixed this by doing this:
app.register_blueprint(api.blueprint)

I have also experienced the same effect in a project. The origin of the problem was an incorrect import of the blueprint file.
Make sure the import statement imports the real blueprint and not the module on which it is defined.
In other words, you may be doing
from .blueprint import blueprint
while you meant
from .blueprint.blueprint import blueprint
As a side recommendation, name the module on which the blueprint is defined with a different name than the blueprint itself, in order to clarify the import. An example:
from .blueprint.views import blueprint

I got an error saying AttributeError: 'Blueprint' object has no attribute 'register_blueprint'
For this I simply uninstalled Flask using pip uninstall flask
and then installed flask[async] pip install flask[async]

I was importing blueprint directly from flask import Flask. I resolved this error by installing flask again using pip3 install flask. Sometimes, if flask version is greater than or equal to 0.12.3 you might face this issue.

Changing the flask version will help. I was using Flask==1.1.2 and changing to Flask==2.0.2 resolves the error.
pip install Flask==2.0.2

Related

Where does Flask look to find config files when using flask.config.from_object()?

I've been trying to solve this for a couple days now. I'm running flask using the application setup as described in the tutorial. Below is are the packages installed in the virtual environment.
pip3 freeze
click==7.1.2 Flask==1.1.2 itsdangerous==1.1.0 Jinja2==2.11.2
MarkupSafe==1.1.1 pkg-resources==0.0.0 python-dotenv==0.15.0
Werkzeug==1.0.1
I have the following in a .env file:
FLASK_APP=myapp
just so I can do flask run. My directory structure looks like:
This is all contained within a directory called 'proj'
init.py
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_object('conf.DevConfig')
app.config.from_mapping(DATABASE=os.path.join(app.instance_path, 'tester.sqlite'))
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
return app
in proj I run flask run and get the following:
werkzeug.utils.ImportStringError: import_string() failed for 'conf.DevConfig'. Possible reasons are:
- missing __init__.py in a package;
- package or module path not included in sys.path;
- duplicated package or module name taking precedence in sys.path;
- missing module, class, function or variable;
Debugged import:
- 'conf' not found.
Original exception:
ModuleNotFoundError: No module named 'conf'
Notice that there is a conf.py in proj/instance/
conf.py contains
class Config(object):
DATABASE = 'tester.sqlite'
class DevConfig(Config):
DEBUG = True
class ProdConfig(Config):
DEBUG = False
Oddly enough, if I put conf.py in proj/ then the application loads just fine. I could have swore I read that Flask will search proj/instance by default for files. Why does it find it when I move it one level back from instance. For that matter can .env files be stored in instance and will flask auto find them? To me it seems like instance_relative_config=True isn't doing what it should be doing. What effect does calling flask run have if it is run in proj/ vs proj/myapp
you can consider this as (Not 100% sure), when you do flask run then create_app function is called and runned.
it is simply as adding a run_app.py file in proj outside of app which import create_app function as as run it
so run_app.py
from app import create_app
app = create_app()
if __name__=='__main__':
app.run()
this will run the server ( as you are doing now)
export FLASK_ENV=app or export FLASK_ENV=run_app.py are same
now as you have added config file in conf.py and it is working fine for you when that file is in proj folder not in instance folder. This is happening because in app/__init__.py file you have define the location of the config object as conf.DevConfig , so python is looking for this object in proj folder either.
since you have define the config object in instance/conf.py file, so python is not able to find it and giving you this error.
To solve This, you need to provide the location of the object in app.config.from_object('conf.DevConfig')
so you can do this in two way,
1st. provide full conf object path from the proj folder like
app.config.from_object('instance.conf.DevConfig')
2nd. import the instance in the app/__init__.py file and then provide the config object
eg. app/__init__.py
"""
import other packages
"""
from instance import conf
def create_app(test_config=None):
"""
app config thing here
"""
app.config.from_object(conf.DevConfig)
"""
config app more
"""
return app
Note in method one i am providng object as a string and in 2 as a class method
app.config.from_object() will search from where flask run is executed. In this case from the /proj directory
app.config.from_pyfile() will search at least in instance when instance_relative_config is set to true
As mentioned by sahasrara62: the devConfig class can be found in conf.py by using 'instance.conf.DevConfig'
I didn't notice any evidence that flask run add a run_app.py file and executes it, but it does seem that flask run starts off in the directory it is run from

python no module named 'A' __init__ vs package

I have looked up several answers on google but none of them made my problem correct.
I made my python file in directory A
in my __init__.py I have app = Flask(__name__)
When I want to get app from other file I use:
from A import app
but error says no module named 'A' so I changed to
from __init__ import app
now it works
Can anyone tell me why from A import app does not work?

Module import Error and NameError in Flask using Heroku

I do have this issue when deploying a small app to heroku, the requirements.txt is very minimal, the app crash with Cannot import module 'NewsApiClient' when using
from newsapi import NewsApiClient
and the app actually start with a 500 Internal Error when using from newsapi import *
NameError: name 'NewsApiClient' is not defined
newsapi = NewsApiClient(api_key='xxxxxxxxxx')
What I've done so far is create an empty init file on the root folder
It appears you are importing the incorrect package in your requirements.txt file. You have imported the newsapi package which is different then the python-newsapi package.
Changing the newsapi==0.1.1 to newsapi-python==0.2.3 should fix your problem with the importing error as long as you reinstall the package dependencies.

PyLint not getting imports in Flask app

I have a Flask app with the following (typical, I think) structure.
repo_name
config.py
requirements.txt
run.py
/service
__init__.py
models.py
schemas.py
views.py
The run.py script has the following content
from service import app
app.run(debug=False, port=8080, host='0.0.0.0')
Inside service.__init__.py I create the Flask app, and at the end, import views.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
ma = Marshmallow(app)
import service.views
The models.py, schemas.py, and views.py are all pretty standard for simple Flask apps, and they also call from service import app or from service import models as needed.
My problem is that PyLint is throwing the error "E0401: Unable to import 'service'" for all these import calls. This is not really a "legitimate" error because I can run the code just fine.
One thing that makes the error go away is changing the import calls to from repo_name.service import .... However, this is undesirable for two reasons
The repo_name is not really related to the app. If I were to go this route, I would probably end up moving everything down a directory. Further, there's no requirement that people name the directory the same way (e.g., someone might clone it as git clone <url> foobar instead of git clone <url> repo_name, which would break code.
More importantly, this doesn't even work. When I make those changes and try to run the server, I get ModuleNotFoundError: No module named 'repo_name'.
How can I make reconcile PyLint and Flask here? Ideally I'd like to fix the issue in the "correct" way, instead of just adding a # pylint: disable= call in front of each import.

How to run flask app after reorganization as a package

I'm trying to restructure a flask app to a package based on http://flask.pocoo.org/docs/0.10/patterns/packages/. My app is based on http://code.tutsplus.com/tutorials/intro-to-flask-signing-in-and-out--net-29982 . I've now changed it to the screenshot above and am trying to run at command line.
runserver.py:
from app import intro_to_flask
if __name__ == '__main__':
intro_to_flask.routes.run(debug=True)
At the command line:
/mini/app (master) $ python runserver.py
Traceback (most recent call last):
File "runserver.py", line 1, in <module>
from app import intro_to_flask
ImportError: No module named app
What am I doing wrong?
Since the Flask documentation mentions only one __init__.py file in the subdirectory with the Flask application and you have two of them, I think you're confused by the __init__.py file and the usage of imports. In your case the subdirectory with the Flask application is intro_to_flask.
Basically it works like this: from <module> import <object>
The module is a .py file and the object is defined inside the module. In this special case there is a __init__.py file so the module you have to reference to has the name of the directory that contains the __init__.py file.
Assuming your app/intro_to_flask/__init__.py looks like this:
from flask import Flask
app = Flask(__name__)
import intro_to_flask.routes
Your app/runserver.py should look like this:
from intro_to_flask import app
app.run(debug=True)
intro_to_flask is the imported module, app is a public object defined inside the imported module.
I believe you're looking for from intro_to_flask import app if I read the links you posted correctly, and assuming you've setup __init__.py correctly inside the intro_to_flask folder.

Categories