So I have this code in my init:
app = Flask(__name__)
app.config.from_object('config')
app.config.from_pyfile('app.cfg')
My folder structure goes like this:
/config.py
/app.cfg
/app/__init__.py
However, this code seems to find my config.py in the root, but it's searching inside my app folder for my app.cfg. How do I make it look for my configuration file in the correct place, without having to put it in my app folder.
Should I be using from object and rename my app.cfg to app.py
According to the official docs (http://flask.pocoo.org/docs/0.10/api/#flask.Config):
from_pyfile(filename, silent=False)
Updates the values in the config from a Python file. This function behaves as if the file was imported as module with thefrom_object() function.
Parameters: filename – the filename of the config. This can either be an absolute filename or a filename relative to the root path.silent – set to True if you want silent failure for missing files.
So, if you don't want to put your cfg file in your app folder one of the things you can do is to set relative route to root folder (that seems to be "./app" directory) in your "from_pyfile" call.
from_pyfile('../app.cfg')
should work..
Related
I have some Python code that references external .ttf font files. I can reference them by including them in the project root folder. I'd like to turn this code into an HTTP Triggered Azure Function.
I see in the docs that I can import external Python modules and files into a Function, but what about non-Python files?
How are these referenced?
When Python code is run locally, they are referenced in the code as:
h1_font = ImageFont.truetype("DejaVuSans-Bold.ttf", h1_size)
h2_font = ImageFont.truetype("Ubuntu-Th.ttf", h2_size)
h3_font = ImageFont.truetype("Ubuntu-Th.ttf", h3_size)
footer_font = ImageFont.truetype("UbuntuMono-R.ttf", footer_size)
What is the filepath when the app is published to Azure?
Here is how the folders are structured locally:
Once published to Azure, the .ttf files are no longer accessible and Function fails
Note: This is a Python Function running on Linux, not Windows.
Update:
My structure:
__init__.py
import logging
import azure.functions as func
from fontTools.ttLib import TTFont
def main(req: func.HttpRequest) -> func.HttpResponse:
font = TTFont('HttpTrigger1/font.ttf')
with open('HttpTrigger1/test.txt', 'r') as file:
data = file.read()
return func.HttpResponse("The content is -----------------"+data)
Original Answer:
How are these referenced?
Put it in the Project folder and use relative path. Then use it as before.
What is the filepath?
Physical path of azure function app is D:\home\site\wwwroot.
Do I just include them in the root folder of the Function and publish?
Yes, just include them in the root folder and then publish the function app, and then you can use relative path to get them.
I'm reading the Flask tutorial and learned that in large application structure the code is moved from single app.py file to 'application factory function' create_app in _init_.py file, then the server can be started like this:
export FLASK_APP=flaskr
export FLASK_ENV=development
flask run
I wonder how does the last command work behind the scene, because there's no explicit call to this factory function anywhere in the code hence no app returned?
Another Flask doc tries to explain why such project structure is used but in that case code in _init_.py creates app explicitly:
from flask import Flask
app = Flask(__name__)
import yourapplication.views
python doc says:
The init.py files are required to make Python treat the
directories as containing packages; this is done to prevent
directories with a common name, such as string, from unintentionally
hiding valid modules that occur later (deeper) on the module search
path. In the simplest case, init.py can just be an empty file, but
it can also execute initialization code for the package or set the
all variable, described later.
The last sentence mentions about 'initialization code' which can be applied in the second case(and simple project structure with app.py file) but I failed to apply it to the first case.
In the flask source code, they check if a function called create_app exists.
# Search for app factory functions.
for attr_name in ('create_app', 'make_app'):
app_factory = getattr(module, attr_name, None)
if inspect.isfunction(app_factory):
try:
app = call_factory(script_info, app_factory)
if isinstance(app, Flask):
return
It evens says so in the documentation:
Flask will automatically detect the factory (create_app or make_app) in myapp.
I'm forced to keep my .env file in a non-standard path outside the root of my project (in a separate directory altogether).
Let's say I have my Django project in /var/projects/my_project, though I have my .env file in /opt/envs/my-project/.env where my SECRET_KEY is stored. In my settings.py file, I'd like to explicitly use the .env file at that path so that I can still do this:
from decouple import config
secret_key = config('SECRET_KEY')
I figured it out.
Instead of importing decouple.config and doing the usual config('FOOBAR'), create a new decouple.Config object using RepositoryEnv('/path/to/env-file').
from decouple import Config, RepositoryEnv
DOTENV_FILE = '/opt/envs/my-project/.env'
env_config = Config(RepositoryEnv(DOTENV_FILE))
# use the Config().get() method as you normally would since
# decouple.config uses that internally.
# i.e. config('SECRET_KEY') = env_config.get('SECRET_KEY')
SECRET_KEY = env_config.get('SECRET_KEY')
Hopefully this helps someone.
If you look at the decouple implementation, config is just a pre-instantiated AutoConfig:
config = AutoConfig()
But AutoConfig takes as optional argument search_path so we can do the following:
from decouple import AutoConfig
config = AutoConfig(search_path='/opt/envs/my-project')
Then you can do as usual:
secret_key = config('SECRET_KEY')
Now, django-decouple==2.1 supports having settings.ini and .env files in any parent directory of the project dir.
(And the old methods don't work anymore. - from decouple import Config, RepositoryEnv does not work, AutoConfig does not have search_path as parameter.)
This is convenient because you would want to keep the settings.ini in the project folder on your local machine and you would want to have clean checkouts on the staging/prod server, thus the settings.ini is better located outside the project folder.
I have the following directory structure for a program I'm writing in python:
\code\
main.py
config.py
\module_folder1\
script1.1.py
\data\
data_file1
data_file2
My config.py is a set of global variables that are set by the user, or generally fixed all the time. In particular config.py defines path variables to the 2 data files, something like path1 = os.path.abspath("../data/data_file1"). The primary use is to run main.py which imports config (and the other modules I wrote) and all is good.
But sometimes I need to run script1.1.py by itself. Ok, no problem. I can add to script1.1 the usual if __name__ == '__main__': and I can import config. But then I get path1 = "../code/data/data_file1" which doesn't exist. I thought that since the path is created in config.py the path would be relative to where config.py lives, but it's not.
So the question is, how can I have a central config file which defines relative paths, so I can import the config file to scripts in different directories and have the paths still be correct?
I should mention that the code repo will be shared among multiple machines, so hardcoding an absolute path is not an option.
You know the correct relative path to the file from the directory where config.py is located
You know the correct relative path to the directory where config.py is located (in your case, ..)
Both of this things are system-independent and do not change unless you change the structure of you project. Just add them together using os.path.join('..', config.path_repative_to_config)
(Not sure who posted this as a comment, then deleted it, but it seems to work so I'm posting as an answer.) The trick is to use os.path.dirname(__file__) in the config file, which gives the directory of the config file (/code/) regardless of where the script that imports config is.
Specifically to answer the question, in the config file define
path1 = os.path.abspath(os.path.join(os.path.join(os.path.join( os.path.dirname(__file__) , '..'), 'data' ), 'data_file1' ) )
I have server running on apache. I use bottle.py. When I'm going to xxx/getbio, SOMETIMES it returns :
Error: 500 Internal Server Error: Template 'bio' not found.
This error occurs not all time: if I restart apache, it's normalizing for several hours, but happens again. Here is code fragment :
#route('/getbio')
def getBio():
return template('bio')
Here is file structure :
xxx/
├── views/
│ ├── bio.tpl
└── index.py
And I didin't missed following lines of code:
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
sys.path.append('views')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
Please help me, because I don't have idea how to fix this bug
Add your template location to TEMPLATE_DIR, not to sys.path:
bottle.TEMPLATE_PATH.insert(0, 'views')
You may find that it's more robust to use the absolute path:
bottle.TEMPLATE_PATH.insert(0, '/path/to/xxx/views')
By default Bottle adds the views folder to the template path for template files. However, at least on Windows, it looks for the views folder relative to where the python script was invoked from (ie. the current working directory) and not relative to where the app entry point .py file is found.
Therefore if your folder structure looks like this:
xxx/
├── views/
│ ├── bio.tpl
└── index.py
and index.py is your Bottle app entry point, you would need to launch index.py with xxx as the current working directory.
Hard-coding the path to the templates folder should work, but is not a portable solution.
You can however specify the absolute path to the templates folder in a portable way by determining it at runtime with code like this:
import os
abs_app_dir_path = os.path.dirname(os.path.realpath(__file__))
abs_views_path = os.path.join(abs_app_dir_path, 'views')
bottle.TEMPLATE_PATH.insert(0, abs_views_path )
Just change the line performing the os.path.join call to correctly construct the abs_views_path relative to your file.
This way, you can simply move the code from machine to machine, and run it from any working directory, and as long as your views folder location is always in the correct place relative to your app it will be found.
AFAIK, bottle has TEMPLATE_PATH constant to store template paths. Try to modify it in the case you want e.g:
from pathlib import Path
from bottle import TEMPLATE_PATH
TEMPLATE_PATH.append(str(Path('path') / 'to' / 'template'))
Then, path/to/template path will be included as one of template paths in your app.
Unfortunately Bottle have a bag in include () function
% include ("my_template.tpl") # template not found
% include("my_template.tpl") # template found
the only difference it is space after "include" is forbidden.
Hope this issue message will help somebody save time in debugging
https://github.com/bottlepy/bottle/issues/1258
And template have to be in bottle.TEMPLATE_PATH
bottle.TEMPLATE_PATH.insert(0, abs_views_path )
If you only pass one keyword argument to the template() function, it will be interpreted as the name of the template file. Example:
return template('<h3>Hello World!</h3>')
If you do not have a template file with the name of '<h3>Hello World!</h3>', you will get a template not found error.
Adding a substitution in the string, and keyword argument to the same line of code will cause Bottle to try and render the first argument as the template itself, instead of searching for it as a file.
return template('<h3>Hello, {{foobar}}</h3>', foobar='foobar')