Why os.path.join(app.root_path, 'flaskr.db')? [duplicate] - python

This question already has an answer here:
Refering to a directory in a Flask app doesn't work unless the path is absolute
(1 answer)
Closed 5 years ago.
In this link http://flask.pocoo.org/docs/0.12/tutorial/setup/#tutorial-setup
In file in flaskr.py :
app = Flask(__name__) # create the application instance :)
app.config.from_object(__name__) # load config from this file , flaskr.py
# Load default config and override config from an environment variable
app.config.update(dict(
DATABASE=os.path.join(app.root_path, 'flaskr.db'),
SECRET_KEY='development key',
USERNAME='admin',
PASSWORD='default'
))
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
The explanation for the line
DATABASE=os.path.join(app.root_path, 'flaskr.db'),
is :
Operating systems know the concept of a current working directory for each process. Unfortunately, you cannot depend on this in web applications because you might have more than one application in the same process.
For this reason the app.root_path attribute can be used to get the path to the application. Together with the os.path module, files can then easily be found. In this example, we place the database right next to it.
Can anyone explain it with example as I am unable to understand the explanation?

I understand it as that: In a normal program, you would first do os.chdir(PATH) and then just open flaskr.db. But, as Flask starts several application (aka app) in a process, each application in a separate thread, but they all share the same "current directory" as the current directory is per-process and not per-thread. In order to be save you should always work with absolute directories and use app.root_path.

Related

Cannot find file in Python flask API [duplicate]

I downloaded nltk data into the data directory in my Flask app. The views reside in a blueprint in another directory on the same level as the data directory. In the view I'm trying to set the path to the data, but it doesn't work.
nltk.data.path.append('../nltk_data/')
This doesn't work. If I use the whole path, it does work.
nltk.data.path.append('/home/username/myapp/app/nltk_data/')
Why does the first form not work? How can I refer to the location of the data correctly?
In Python (and most languages), where the code resides in a package is different than what the working directory is when running a program. All relative paths are relative to the current working directory, not the code file it's written in. So you would use the relative path nltk_data/ even from a blueprint, or you would use the absolute path and leave no ambiguity.
The root_path attribute on an app (or blueprint) refers to the package directory for the app (or blueprint). Join your relative path to that to get the absolute path.
resource_path = os.path.join(app.root_path, 'enltk_data')
There's probably no reason to be appending this folder every time you call a view. I'm not familiar with nltk specifically, but there's probably a way to structure this so you set up the data path once when you create your app.
project / app / blueprint
/ data
^ join with root_path to get here
^ app.root_path always points here, no matter where cwd is
^ current working directory

How can you get the filepath of a file in flask?

I have a flask application which is utilizing Fabric to deploy code to certain machines.
One particular method, fabric.contrib.files.upload_template, requires a filename which is the path of a file I would like to upload to my remote machines.
I have a file, index.php, which I want to place on my remote machines. I want to use upload_template to accomplish this task.
Where should I place 'index.php' in my flask folder? How will I be able to obtain the path of index.php for upload_template?
Please note that:
My application is hosted on Heroku so the typical /home/Sparrowcide/flaskapp/path/to/file won't work.
I know I can probably get away by invoking a method which writes to /tmp/path/to/file, but I'd rather not as this is not a very elegant solution.
Well the short answer is that you can pretty much put it wherever you want, I don't think flask will enforce any sort of structure on you here. However I personally would create a subdirectory called data and then in the flask app I might do something like this:
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'index.php')
Or, if I felt I was likely to re-use this information (eg if i had multiple files to upload), I might break it out into multiple variables:
SRCDIR = os.path.dirname(os.path.abspath(__file__))
DATADIR = os.path.join(SRCDIR, 'data')
whatever_upload_function(os.path.join(DATADIR, 'index.php'))

Python Change Directory Google App Engine

I have my webapp written in Python running on Google App Engine; so far only testing in my localhost. My script needs to read text files located in various directories. So in my Python script I would simply use os.chdir("./"+subdirectory_name) and then start opening and reading the files and using the text for analysis. However I cannot do that when trying to move it over to App Engine.
I assume I need to make some sort of changes to app.yaml but I'm stuck after that. Can anyone walk me through this somewhat thoroughly?
From the answer below, I was able to fix this part, I have a followup question about the app.yaml structure though. I have my folder set up like the following, and I'm wondering what I need to put in my app.yaml file to make it work when I deploy the project (it works perfectly on localhost right now).
Main_Folder:
python_my_app.py
app.yaml
text_file1
text_file2
text_file3
subfolder1_with_10_text_files_inside
subfolder2_with_10_text_files_inside
subfolder3_with_10_text_files_inside
...how do I specify this structure in my app.yaml and do I need to change anything in my code if it works right now on localhost?
You don't need to change your working directory at all to read files. Use absolute paths instead.
Use the current file location as the starting point, and resolve all relative paths from there:
import os.path
HERE = os.path.dirname(os.path.abspath(__file__))
somefile = os.path.abspath(os.path.join(HERE, 'subfolder1_with_10_text_files_inside /somefile.txt'))
If you want to be able to read static files, do remember to set the application_readable flag on these, as Google will otherwise only upload them to their content delivery network, not to the app engine.
You can package your text files inside your application and then do something like this:
path = os.path.join(os.path.dirname(__file__), 'subdir', 'file')
file = open(path)

Configuring celery with a .conf file

Good day.
I set up a separate project from the main one called myproject-celery. It is a buildout based project which contains the async part of my project. For convenience I want to have a file, that will be containing this machine's configuration. I know that celery provides the python config file, but I do not like this configuration style.
Let's say I have a configuration in a Yaml config file named myproject.yaml
What I want to achieve:
./bin/celery worker --config /absolute/path/to/project/myproject.yaml --app myproject.celery
The problem really is that I want to specify the file's location, because it can change. I tried writing a custom loader class, but I failed, cause I do not even know why and when the many custom methods of this class are called (the only doc that I found is http://docs.celeryproject.org/en/latest/reference/celery.loaders.base.html?highlight=loader#id1 and It's no help for me). I tried to do something on import phase for the app module, but I can not pass the filepath to that module's code... The only solution that I came up with was using a custom ENV param that will contain the path, but I do not see why can't it be a launch param like in most apps, that I use(refering to pyramid with it's paster serve myproject.ini)
So the question:
What do I have to do to set up the config from a file that I could specify by an absolute path?
EDIT:
The question was not answered, sow I posted an issue on celery's github. Will wait for a response.
https://github.com/celery/celery/issues/1100
Looking at celery.loaders.base it looks like the method you want to override is read_configuration:
from celery.datastructures import DictAttr
from celery.loaders.base import BaseLoader
class YAMLLoader(BaseLoader):
def read_configuration():
# Load YAML file here and return a DictAttr instance

Dynamically running python code on google app engine

I am trying to be able to dynamically run python code, with variables being able to be passed through to the code. I was able to do this on my computer before I added my project to the google app engine environment (because I can access all the files, but now, with google app engine, I can not do that.
I am struggling to find a solution to this problem. It does not need to be too terribly fancy, just send variables in and get html out, as well as scripts being able to be added client side (the crucial part) to whatever database method that is used.
Edit:
well basically what I mean by dynamically is so that I can import (or thats what I did in IDLE when I tested the prototype, the solution will probably not be called importing) a python script with the name of the library being stored in a variable, as well as an unknown number of variables that would be added. I got this to work on Idle, but now I need to get it to work in the google app engine environment, and people need to be able to upload scripts as well (which is the main problem that cascades into many more problems)
Edit:
When I say that I managed to get this to work on my local machine, I mean I was able to manually drop scripts into the same directory as my main script. The script would later import and execute the scripts when necessary. I was able to get this to work with the following code:
#calling function
mod = __import__('actions.'+folder+'.'+FILE)
VAR = getattr(getattr(mod, folder), FILE)
response = VAR.Main()
print response
This code worked on both my laptop and in the google app engine environment, But When I try to add more scripts to the directory is when things get problematic. On my laptop I could just move the file over one way or another because I had full access to the file directory. On Google App engine I do not have the ability to just upload a file to the same directory or subdirectory of the rest of my python scripts. So basically the problem comes up when trying to design a way to allow more code to come into the system (in my case, adding more 'plugins').
The answer is the exec statement (also known as the exec() function) or the eval() function. See http://docs.python.org/reference/simple_stmts.html#the-exec-statement and http://docs.python.org/library/functions.html?highlight=eval#eval. These can execute arbitrary Python code from a string. exec() runs a script and you get the side effects; eval() takes an expression and returns its value. Typically you pass input in as variables in the local namespace.
Ok, So what I eventually did was use the datastore to upload everything such as the name, description, uploader and code of the plugin (for now the code is just entered into a textarea box). I then, instead of importing a file located in a folder under the same directory of my code like I had before when running everything off of my desktop, Imported the plaintext code into a module using this little bit of magic:
#Initiating Variables for use by importing functions
module_name = 'mymod'
filename = 'action_file'
source = PossibleMatches[0][1] #the source code from the best matched option
# define module_name somewhere
import types
module = types.ModuleType(module_name)
# source should the code to execute
# filename should be a pseudo-filename that the code's from
# (it doesn't actually have to exist; it's used for error messages)
code_object = compile(source, filename, 'exec')
#execute the code in the context of the module
exec code_object in module.__dict__
#Executing the 'Main' Function from the code
return module.Main()

Categories