Reputation: 1035
When create a Flask instance , we always use __name__
as the first arguments,
but why?
class flask.Flask(import_name, static_path=None, static_url_path=None,static_folder='static', template_folder='templates', instance_path=None, instance_relative_config=False)
The official document says that first parameter is used to find resource,how?
Upvotes: 6
Views: 2267
Reputation:
__name__
should not always be used as the first argument particularly if the application is in a package instead of a single module, then its 'usually recommended to hardcode the package name' in order to simplify debugging with the Flask-SQLAlchemy extension for example. For reference see the section on 'About the First Parameter' in http://flask.pocoo.org/docs/0.10/api/.
In the case when using a package there is a way to avoid hardcoding the package name with a special configuration which forces __name__
to resolve to the package name as desribed in Larger Applications. First, note that a Python package is not simply a directory containing modules which are Python source files; it must also contain an __init__.py
file (except for Python3 namespace packages). One function of __init__.py
files is to prevent unintentional namespace conflicts as mentioned in An Introduction to Python: Section 6.4. In the case of flask, its convenient to define a flask app in a package's __init__.py
in order to enable use of __name__
since in that case it resolves to the package name which is identical to the package's base directory name and has a file attribute with which its absolute pathname can be determined. A working flask/Python3 project demonstrating this configuration is available at flaskdemo.
Regarding understanding the first parameter in flask instance initialization, first of all if its missing and there are no remaining arguments, then when attempting to run the flask app it immediately fails with "TypeError: __init__()
missing 1 required positional argument: 'import_name'". Second, if a nonexistent pathname is provided for it, then the application's and its resources root is set to the cwd (current working directory) and attempts to access resources would fail unless they are in the cwd which is not necessarily always the case and a limitation anyway.
Further details can be obtained by examining the flask sources, particularly app.py as well as helpers.py. In an Anaconda3 installation they are located in Lib\site-packages\flask. From a brief review, what I found is that class Flask is defined in app.py and its
__init__
method begins with:
def __init__(self, import_name, static_path=None, static_url_path=None,
static_folder='static', template_folder='templates',
instance_path=None, instance_relative_config=False):
_PackageBoundObject.__init__(self, import_name, template_folder=template_folder)
...
class _PackageBoundObject is defined in helpers.py and it has an open_resource()
function
that returns open(os.path.join(self.root_path, resource), mode)
where
self.root_path = get_root_path(self.import_name)
The root in root_path
refers to 'the path of a package or the folder that contains a module'. get_root_path
goes though a series of attempts to resolve it starting with the module name if its available and has a file attribute. In all cases absent exceptions it returns an absolute pathname which defaults to cwd if it has not been already been resolved with a module name whenpkgutil.get_loader(import_name) == None
or import_name == '__main__'
, which happens when running a flask app interactively instead of from a file.
Upvotes: 1
Reputation: 159935
The import name is used to resolve the directory where the Flask application is installed (see the get_root_path
function in flask/helpers.py). This makes it possible for things like render_template
, send_static_file
, and relative file paths in config
to resolve to files in the application's folder without needing a file path to be provided.
Consider an extremely simple Python app without this functionality:
print("Running simple_app")
with open('the-folder/simple.file', 'r') as f:
for line in f:
print(f)
Hello
World!
And a directory structure looking like this:
some-path/
simple-app/
simple_app.py
the-folder/
simple.file
If we start Python while our current working directory is simple-app/
everything will work just fine:
simple-app$ python simple_app.py
Running simple_app
Hello
World!
But if we move up one folder and try again:
some-path$ python simple-app/simple_app.py
Traceback (most recent call last):
IOError: [Errno 2] No such file or directory: 'the-folder/simple.file'
The same thing happens when we move down one folder. However, if we could get the location of simple_app.py
on the file system, we could then os.join
the directory in which simple_app.py
was installed with the-folder/simple.file
with open(os.join(SIMPLE_APP_DIR, 'the-folder/simple.file', 'r') as f:
And our working directory wouldn't matter, since we would always be dealing with an absolute path. This is what Flask does, and this is why it needs the __name__
passed in.
Upvotes: 10
Reputation:
It is explained in the Quick Start section of docs.
http://flask.readthedocs.org/en/latest/quickstart/#a-minimal-application
Quoting from the docs
The first argument is the name of the application’s module or package. If you are using a single module (as in this example), you should use
__name__
because depending on if it’s started as application or imported as module the name will be different (__main__
versus the actual import name). This is needed so that Flask knows where to look for templates, static files, and so on.
Upvotes: 0