Flask CLI command not in __init__.py file - python

I'm trying to add commands to my Flask app.
This is my __init__.py file:
import os
from flask import Flask
from flask_cors import CORS
from flask_mongoengine import MongoEngine
app = Flask(__name__)
CORS(app)
app.config.from_object(os.environ['APP_SETTINGS'])
db = MongoEngine(app)
import slots_tracker_server.views # noqa
If I add to it:
#app.cli.command()
def test_run():
print('here')
I can run flask test_run with no problems, but if I try to move the code to another file, for example: commands.py, I get the error Error: No such command "test_run". when trying to run the command.
What I'm missing?

Use click (the library behind Flask commands) to register your commands:
# commands.py
import click
#click.command()
def test_run():
print('here')
In your __init__.py import and register the commands:
# __init__.py
from yourapp import commands
from flask import Flask
app = Flask(__name__)
app.cli.add_command(commands.test_run)
Take a look at the official docs

In you commands.py you can add register function like that:
def register(app):
#app.cli.command(name='test_run', help="test_run command")
def register_test_run():
test_run()
# other commands to register
And then in your __init__.py import this register function
from flask import Flask
app = Flask(__name__)
from commands import register
register(app)
Notice, that you should import register after you've initialized your app.

Related

Importing modules from parent folder does not work when running flask app

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.

How do I use Flask.route with Flask

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.

python unittest ModuleNotFoundError: No module named <...>

I tried to crate simple Python project with flask and unittest. Structure is quite simple:
classes
|-sysinfo
|static
|templates
|- index.html
|- layout.html
|__init__.py
|sysinfo.py
|printinfo.py
tests
|test_sysinfo.py
README.md
requirments.txt
Very simple class in printinfo.py:
#!/usr/bin/python
import psutil
import json
class SysInfo:
.......
def displayInfo(self):
.......
return json.dumps(self.__data)
And simple flask server run with sysinfo.py:
from flask import Flask, flash, redirect, render_template, request, session, abort
from printinfo import SysInfo
import json
obj1 = SysInfo("gb")
app = Flask(__name__)
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html',**locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
del obj1
I run it with python sysinfo.py staying in classes/sysinfo folder and everything works ok.
So I decided to run unittest for my application. Put in classes/tests ( also tried classes/sysinfo/tests) file test_sysinfo.py with code:
import unittest
import printinfo
from sysinfo import sysinfo
import json
import sys
class TestFlaskApi(unittest.TestCase):
def setUp(self):
self.app = sysinfo.app.test_client()
def simple_test(self):
response = self.app.get('/health')
self.assertEqual(
json.loads(response.get_data().decode(sys.getdefaultencoding())),
{'healthcheck': 'ok'}
)
if __name__ == "__main__":
unittest.main()
And when I started it I can see error:
Error Traceback (most recent call last):
File "\Python\Python37-32\lib\unittest\case.py", line 59, in testPartExecutor
yield File "\Python\Python37-32\lib\unittest\case.py", line 615, in run
testMethod() File "\Python\Python37-32\lib\unittest\loader.py", line 34, in testFailure
raise self._exception ImportError: Failed to import test module: test_sysinfo Traceback (most recent call last): File
"\Python\Python37-32\lib\unittest\loader.py", line 154, in
loadTestsFromName
module = __import__(module_name) File "\classes\sysinfo\tests\test_sysinfo.py", line 2, in <module>
import printinfo ModuleNotFoundError: No module named 'printinfo'
I read several articles, some topics here on StackOverflow for my understanding it's related to project structure. I tried to create setup.py and setup.cfg. I managed to start it with this setup, but test still didn't work.
Could you please help me with minimum setup applicable for my case? All the material I found had written for specific case or too general. I cannot apply it for my case.
Follow flask tutorial I edit __init__.py file to start app from here:
from flask import Flask, flash, redirect, render_template, request, session, abort
from . import printinfo
import json
import os
obj1 = printinfo.SysInfo("gb")
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
obj1 = printinfo.SysInfo("gb")
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html', **locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
#del obj1
return app
Also environment variables should be set for Flask:
For Linux and Mac:
export FLASK_APP=sysinfo
export FLASK_ENV=development
For Windows cmd, use set instead of export:
set FLASK_APP=sysinfo
set FLASK_ENV=development
And run application:
flask run
It run application on localhost on port 5000 since development env set. Anyway I needed to add from . import printinfo into __init__.py.
Didn't try test, but think it should work. If interesting will update soon.
Just followed Flask tutorial. Created conftest.py and test_factory.py. Run Ok with pytest:
import pytest
from sysinfo import create_app
from sysinfo import printinfo
#pytest.fixture
def app():
app = create_app({
'TESTING': True
})
with app.app_context():
printinfo.SysInfo("gb")
yield app
Probably the same setup could be used with unittest. Didn't try.

Flask app does not use routes defined in another module

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.

python imp.load_source with dependencies

My app has the following layout:
/wsgi/myapp/__init__.py
/wsgi/application
/app.py
File _init_.py:
from flask import Flask #python flask framework!
def create_app(app_name=None):
app_name = app_name or __name__
app = Flask(app_name)
return app
File application (without .py extension!):
from myapp import create_app
application = create_app('myapp')
#application.route('/', methods=['GET', 'POST'])
def index():
return 'My OpenShift Flask app'
File app.py has the following line which causes error:
import imp
app = imp.load_source('application', 'wsgi/application')
The error is "No module named myapp". What else I need to solve the issue?
add the import path
import sys
sys.path.append('wsgi')
import imp
app = imp.load_source('application', 'wsgi/application')
Does it work?
import imp
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
wsgi = imp.load_source('wsgi', 'application.py')
application = wsgi.application
this should work in python 3

Categories

Resources