I am writing a flask app which follows the following folder structure.
backend
server.py
__init__.py
test
__init__.py
servertest.py
"""Server ping test for flask"""
import flask
import pytest
from server import app
#pytest.fixture()
def client():
yield testing.TestClient(app)
def test_ping_resource(client):
doc = "Flask GET service is working"
result = client.simulate_get("/api/ping")
assert result.status_code == 200
assert result.json == doc
And this is my test file. When I am running the file. it gives
from server import app
E ImportError: No module named 'server'
What am I doing wrong, which is making the server module invisible to test module?
When you run a python file, its parent folder is added to the python path, but the parent of its parent (here, your root folder) is not!
What you could do is:
running your tests from the root folder (preferred)
Using relative imports, here: from ..server import app
Modify your python path (not advised)
Python imports modules from a list of path:
import sys
sys.path
You have to provide Python a way to find server.py:
you can run your code from the backend directory, because the current path is automatically happened to sys.path (cd backend; pytest)
you can add the full path to backend to PYTHONPATH
At some point, you will need to read the doc about import.
Also, to use pytest naturally, your test files must start with test.
Related
I have this structure in FastAPI.
project_folder/
project_folder/app/
project_folder/app/main.py (with app object of FastAPI)
project_folder/app/rest/panel.py (here I try import app object from main)
In panel.py I import by:
from ..main import app
or
from app.main import app
Its works with other files... like "from app.models import XYZModel".
I run by command:
bash -c "uvicorn main:app --host 0.0.0.0 --port 8000 --reload"
and I try this:
bash -c "uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
It works. All paths and imports to multiple files inside different directories work fine. The problem is only when I try to import the app object from main.
I got error like this:
Error loading ASGI app. Could not import module "main".
Notice that there are many confusing things in your solution:
conflicting name between package name and object name : app
what the root source path for your project
I suggest:
rename the directory app into src, and consider it your source root
when you import, try to use abs import: from main import app
run server inside src folder and user uvicorn main:app
I am developing an app and the development setup was really easy.
I run it locally with:
$ . .venv/bin/activate
(.venv) $
(.venv) $ python -m flask run
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:8080
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: -###-###
and I have configured apache2 on my (ubuntu) laptop with:
ProxyPass / http://127.0.0.1:8080
My code is structured like:
app.py
pages/scc_main/scc.html
...
The code has this:
import re
import jinja2
from flask import Flask
from flask import request
import data
app = Flask(__name__)
env = jinja2.Environment(loader=jinja2.FileSystemLoader("pages"))
#app.route('/')
def hello_world():
return '<h2>Hello, World!</h2>'
#app.route('/contracts/scc')
#app.route('/contracts/scc/')
def contracts_main():
main = env.get_template('scc_main/scc.html')
context = data.build('scc_main')
return main.render(**context)
And everything works great. As in:
$ curl 'http://localhost/'
<h2>Hello, World!</h2>$
But when I deploy. Wow. I set my site's root to point to the app. That is actually working. I can hit https://opencalaccess.org/ and it gets my static content.
I have:
import sys
import logging
logging.basicConfig(
level=logging.DEBUG,
filename='/var/www/<full-path>/logs/contracts_scc.log',
format='^(asctime)s %(message)s')
sys.path.insert(0, '/var/www/<full-path>')
sys.path.insert(0, '/var/www/<full-path>/.venv/lib/python3.8/site-packages')
And https://opencalaccess.org/contracts/scc works. But only after I change the Environment call above to:
env = jinja2.Environment(loader=jinja2.FileSystemLoader("/var/www/full-path>/pages"))
Now, any link which is just a link is fine. But anything that looks at the flask.request.path gives me:
The browser (or proxy) sent a request that this server could not understand.
What the heck? Setting up the dev environment was so easy. What do you have to do to get this working in deployment? Any suggestions?
ADDED:
Well, it seems clear that it is the WSGI part that is having the problem. My script is not receiving the request structure and so it cannot read any parameters. I have all my parameters on the URL, so my data building method reads the request.path to see what to do.
So, where to go from here. We will see.
I am no longer able to reproduce this.
I'm trying to follow the instructions given here: Adding a favicon to a Flask server without HTML on how to add a favicon to a flask app, however its not working for me. Here is my application file:
from flask import Flask,send_from_directory
application=Flask(__name__)
#application.route('/')
def main():
return '<html><p>hello world</p></html>'
#application.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(application.root_path, 'static'),
'favicon.ico',mimetype='image/vnd.microsoft.icon')
if __name__=='__main__': application.run(debug = True)
and here is my directory structure:
➜ demo ls -R
application.py static
./static:
favicon.ico
When I run the application in Firefox, no favicon is shown, and when I run it in Chrome, the default favicon is shown. I used this website to convert a png into an ico file:
https://www.freeconvert.com/png-to-ico
Please let me know where I'm going wrong.
When I run the app in chrome, I get this error in the console:
GET http://localhost:5000/favicon.ico 500 (INTERNAL SERVER ERROR)
I needed to import os, here is the working application:
from flask import Flask,send_from_directory
import os
application=Flask(__name__)
#application.route('/')
def main():
return '<html><p>hello world</p></html>'
#application.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(application.root_path, 'static'),
'favicon.ico',mimetype='image/vnd.microsoft.icon')
if __name__=='__main__': application.run(debug = True)
This error is something that repeatedly and seemingly randomly occurs and I always have difficulty fixing it. I have read all the other posts on this issue and I still can't fix it.
My directory layout is the following
> /data
> .gitignore
> Pipfile
> Pipfile.lock
> README.md
> run.py
> /web_app
> /models
> /routes
> /templates
> init.py
Here is init.py
from flask import Flask
from web_app.routes.home_routes import home_routes
from web_app.routes.json_routes import json_routes
from web_app.routes.insert_routes import insert_routes
app = Flask(__name__)
app.register_blueprint(home_routes)
app.register_blueprint(json_routes)
app.register_blueprint(insert_routes)
app.run(debug=True)
Here is run.py
from web_app import app
I open /data
I execute: set FLASK_APP=web_app
I execute: run flask
I receive this common error:
Error: Could not import "web_app".
I thought I had perfectly fulfilled the necessary directory design for flask yet it still occurs.
Try renaming
init.py
file in /data/web_app directory to
__init__.py
I think I figured out whats wrong. When I ran flask run in web_app directory, THEN it worked. Though I still don't understand the logic of how flask reads/runs flask directories, so I'm worried it will happen again.
Try renaming init.py to __init__.py and import as
from .web_app import app
I have a basic flask-restful application with a structure that looks like this as recommended on the flask website.
/application
/application
/config.py
/__init__.py
/wsgi.ini
Slightly irrelevant, but config.py is generated by our CD server.
wsgi.ini looks likes this
[uwsgi]
module = application:app
master = true
processes =5
socket = /tmp/application.sock
chmod-socket = 660
vacuum = true
die-on-term = true
and __init__.py looks something like this
import config
from flask import Flask, request, g
from flask_restful import Resource, Api, abort
app = Flask(__name__)
api = Api(app)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Now when I try to startup the application using uwsgi --ini wsgi.ini I get this error:
File "./application/__init__.py", line 2, in <module>
import config
Originally __init__.py was called main.py and I executed that to debug, which is why the import is now wrong. I'm guess I will need to change the import to be from .config import *
My question is two fold:
Could I have avoided the import problem completely. ie is there a way in python3 to import sibling modules that will work for both approaches
is my wsgi.ini in the correct place, or should it be in the inner application directory?
Python 3.x dropped support for infra-package relative imports. You need to use an absolute import:
from application import config
or the new spelling of relative imports:
from . import config
If you need to also support legacy versions of Python you can enable this behavior with:
from __future__ import absolute_import