Python Flask Frozen has no attribute 'url_default_functions' - python

I have written my 1st Python API project with Flask and now am trying to deploy it to Netlify.
Searched online and found I need to use Flask-Frozen to generate a static website.
Not sure I'm doing it correctly, because my project is a API project not a website project, so may be I should not use Flask-Frozen(FF)?
But if I could still use FF to generate static website for my API project, here is my project:
--
app.py
mazesolver
mazeapi.py
Here is the app.py
from flask_frozen import Freezer
from mazesolver import mazeapi
# Call the application factory function to construct a Flask application
# instance using the development configuration
# app = mazeapi()
# Create an instance of Freezer for generating the static files from
# the Flask application routes ('/', '/breakfast', etc.)
freezer = Freezer(mazeapi)
if __name__ == '__mazeapi__':
# Run the development server that generates the static files
# using Frozen-Flask
freezer.run(debug=True)
mazeapi.py
import io
from mazesolver.solver import MazeSolver
from markupsafe import escape
from flask import Flask, flash, request, redirect, send_file
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = { 'png', 'jpg', 'jpeg' }
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
#app.route('/maze/<mazename>')
def maze(mazename):
return 'maze 4 %s' % escape(mazename)
Whenever I run:
python app.py
I got this error:
Traceback (most recent call last):
File "app.py", line 10, in <module>
freezer = Freezer(mazeapi)
File "/home/winstonfan/anaconda3/envs/maze/lib/python3.7/site-packages/flask_frozen/__init__.py", line 98, in __init__
self.init_app(app)
File "/home/winstonfan/anaconda3/envs/maze/lib/python3.7/site-packages/flask_frozen/__init__.py", line 108, in init_app
self.url_for_logger = UrlForLogger(app)
File "/home/winstonfan/anaconda3/envs/maze/lib/python3.7/site-packages/flask_frozen/__init__.py", line 588, in __init__
self.app.url_default_functions.setdefault(None, []).insert(0, logger)
AttributeError: module 'mazesolver.mazeapi' has no attribute 'url_default_functions'

I had the same issue and added
url_default_functions={}
to the app, right before
if __name__ == "__main__":
app.run()
I guess you could put it right after
app = Flask(__name__)
and the error went way... but there are many more :) It seems that frozen-flask isn't working with the lastest flask, but I couldn't get any other versions working with it.
Did you manage to get it working?

You have a simple namespace bug.
In the code you've posted, you are freezing your module mazeapi, not the actual Flask application, mazeapi.app.
Try changing your Freezer call in line 10 of app.py to:
freezer = Freezer(mazeapi.app)

Related

Complaining not a "package" though there is a __init__.py file in the folder

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.

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.

Can not import mongo object in other file

Using flask-restful, i can not import the object mongo = PyMongo() from the file app/__init__.py into app/common/db.py.
My folder structure looks like this:
myproject/
run.py
app/
__init__.py
config.py
common/
__init__.py
db.py
auth/
__init__.py
resources.py
app/__init__.py contains:
from flask import Flask, Blueprint
from flask_pymongo import PyMongo
from flask_restful import Api
from app.config import Config
from app.auth.resources import Foo
mongo = PyMongo()
bp_auth = Blueprint('auth', __name__)
api_auth = Api(bp_auth)
api_auth.add_resource(Foo, '/foo/<string:name>')
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
mongo.init_app(app)
app.register_blueprint(bp_auth)
return app
app/common/db.py contains:
from app import mongo
the application itself is run from the root via run.py which contains:
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
Problem:
Running the application i get an ImportError:
from app import mongo
ImportError: cannot import name 'mongo'
Why this is not working?
Thanks for your help!
EDIT:
Full Traceback:
Traceback (most recent call last):
File "run.py", line 1, in <module>
from app import create_app
File "/home/bt/Dropbox/dev/flask/test_api/app/__init__.py", line 13, in <module>
from app.auth.resources import SignIn, Users, User, Foo
File "/home/bt/Dropbox/dev/flask/test_api/app/auth/resources.py", line 8, in <module>
from app.common.resources import AuthResource
File "/home/bt/Dropbox/dev/flask/test_api/app/common/resources.py", line 3, in <module>
from app.auth.decorators import token_required
File "/home/bt/Dropbox/dev/flask/test_api/app/auth/decorators.py", line 6, in <module>
from app.common.database import users
File "/home/bt/Dropbox/dev/flask/test_api/app/common/database.py", line 1, in <module>
from app import mongo
ImportError: cannot import name 'mongo'
As I suspected, this is a circular import problem.
You can track the closed loop of dependencies looking at the traceback:
app -> resources -> database -> app
This is a common mistake and not properly documented in Flask tutorials. As explained here by Lepture, you should avoid declaring db in the __init__.py
I always keep this one certain rule when writing modules and packages:
Don't backward import from root __init__.py.
How should you do it, then?
declare db in the proper module (db.py)
import it inside the application factory
I found myself reluctant towards this pattern, I thought those import statements didn't belong inside a function. But this is the way to go.
So, your files should look something alike:
app/common/db.py
from flask_pymongo import PyMongo
mongo = PyMongo
app/__init__.py
from flask import Flask
...
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
from app.common.db import mongo
mongo.init_app(app)
...
and when you need your database connection, i.e. in resources module, you should import it like
from app.common.db import mongo
Note: to avoid future problems, your blueprints should also be declared elsewhere and import on creation time. I really encourage you to read the post by Lepture to better understand this approach.

"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.

Heroku python console app module ImportError

I've encountered an issue while trying to access PostgreSQL from heroku python console (first attempt).
First up, I launch python using $ heroku run python
Then I try to load up the db module with >>> from app import db, this action returns:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named app
I have one web dyno running python which has app = Flask(__name__), apart from that, I don't know what other details should I provide in order to shed more light into the issue.
After experimenting with the terminal, it became clear, that there really is no way for it to know what variables do I have in my main.py, so what I did then was load the main parts of the app through the terminal like so:
>>> import os
>>> from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
>>> from flask.ext.sqlalchemy import SQLAlchemy
>>> # create the application
>>> app = Flask(__name__)
>>> app.config.from_object(__name__)
>>> app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', 'some-url.com')
>>> db = SQLAlchemy(app)
And from then on I was able to access the db object as intended.
EDIT - the issue completely resolved below.
So the reason I was having an error while trying to import my apps code into the python shell was two fold:
The *.py that was the target of my import was not at the root directory, I was telling the shell to look in the wrong place.
Since the *.py I was importing was not named app.py (and I was asking to from app import db), I was also telling the shell to look for the wrong file.
The way to solve this issue was to append the path of my *.py file to the sys.path and instead of from app import db, us from my_filename_without_the_extenssion import db. For a summary, the shell received these instructions:
>>> import sys
>>> sys.path.append('path/to/my/file')
>>> from my_filename_without_the_extenssion import db
>>> # to test if everythings ok
>>> db

Categories

Resources