如何理解Flask实例init中的第一个参数?

时间:2015-08-02 03:48:00

标签: python flask

创建Flask实例时,我们总是使用__name__作为第一个参数, 但为什么呢?

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)

官方文档说第一个参数用于查找资源,如何?

3 个答案:

答案 0 :(得分:4)

导入名称用于解析安装Flask应用程序的目录(请参阅get_root_path中的flask/helpers.py功能)。这使得render_templatesend_static_fileconfig中的相对文件路径等内容可以解析为应用程序文件夹中的文件,而无需提供文件路径。

考虑一个非常简单的Python应用,不用这个功能:

simple_app.py

print("Running simple_app")

with open('the-folder/simple.file', 'r') as f:
    for line in f:
        print(f)

simple.file

Hello
World!

目录结构如下:

some-path/
    simple-app/
        simple_app.py
        the-folder/
            simple.file

如果我们启动Python而我们当前的工作目录是simple-app/,一切都会正常工作:

simple-app$ python simple_app.py
Running simple_app
Hello
World!

但是如果我们向上移动一个文件夹再试一次:

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'

当我们向下移动一个文件夹时,会发生同样的事情。但是,如果我们可以在文件系统上获取simple_app.py的位置,那么我们可以os.join simple_app.py安装the-folder/simple.file的目录{/ 1}}

with open(os.join(SIMPLE_APP_DIR, 'the-folder/simple.file', 'r') as f:

我们的工作目录无关紧要,因为我们总是在处理绝对路径。这就是Flask的作用,这就是它需要传递__name__的原因。

答案 1 :(得分:1)

__name__不应该总是用作第一个参数,特别是如果应用程序在一个包而不是一个模块中,那么它通常建议硬编码包名称'例如,为了简化Flask-SQLAlchemy扩展的调试。有关参考,请参阅'关于第一个参数'在http://flask.pocoo.org/docs/0.10/api/

在使用软件包的情况下,有一种方法可以避免使用特殊配置对软件包名称进行硬编码,这会强制__name__解析为Larger Applications中所述的软件包名称。首先,请注意Python包不仅仅是包含Python源文件模块的目录;它还必须包含__init__.py文件(Python3 namespace packages除外)。 __init__.py文件的一个功能是防止An Introduction to Python: Section 6.4中提到的无意的命名空间冲突。在烧瓶的情况下,方便在包__init__.py中定义烧瓶应用程序以便能够使用__name__,因为在这种情况下它解析为与...相同的包名称包的基本目录名称,并具有一个文件属性,可以使用该属性确定其绝对路径名。可以在flaskdemo获得演示此配置的工作瓶/ Python3项目。

关于理解flask实例初始化中的第一个参数,首先如果它丢失并且没有剩余的参数,那么当试图运行烧瓶应用程序时它会立即失败,并且" TypeError:__init__()丢失1必需的位置参数:' import_name'"。其次,如果为它提供了不存在的路径名,则应用程序及其资源根目录设置为cwd(当前工作目录),并且尝试访问资源将失败,除非它们位于cwd中,这不一定总是案件和限制无论如何。

通过检查烧瓶来源,特别是app.py以及helpers.py,可以获得更多细节。在Anaconda3安装中,它们位于Lib \ site-packages \ flask中。从简短的回顾中,我发现Flask类是在app.py及其中定义的 __init__方法以:

开头
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在helpers.py中定义,它有一个open_resource()函数 返回open(os.path.join(self.root_path, resource), mode)其中

self.root_path = get_root_path(self.import_name)

root_path中的根指的是包的路径或包含模块的文件夹'。 get_root_path通过一系列尝试来解决它,如果模块名称可用且具有文件属性,则从模块名称开始。在没有异常的所有情况下,它返回一个绝对路径名,如果在pkgutil.get_loader(import_name) == Noneimport_name == '__main__'时尚未使用模块名称解析,则默认为cwd,这是在以交互方式运行烧瓶应用程序而不是从一份文件。

答案 2 :(得分:0)

在文档的“快速入门”部分对此进行了解释。

http://flask.readthedocs.org/en/latest/quickstart/#a-minimal-application

从文档引用

  

第一个参数是应用程序模块或包的名称。如果您使用单个模块(如本示例所示),则应使用__name__,因为根据它是作为应用程序启动还是作为模块导入,名称将不同(__main__与实际导入名称)。这是必需的,以便Flask知道在哪里查找模板,静态文件等。