Flask1.0.2系列(十) 配置处理

英文原文地址:http://flask.pocoo.org/docs/1.0/config/

若有翻译错误或者不尽人意之处,请指出,谢谢~


        (新增于版本0.3)

        应用程序需要一些配置。根据不同的应用程序环境,你可能希望更改某些设置项,比如是否开启调试模式,设置密钥,或者其他环境所需的东西等等。

        Flask被设计为需要配置才能启动应用程序。你可以将配置硬编码到代码中,这对小的应用程序来说并不坏,但这里还有更好的方式。

        不论你怎么加载你的配置,这里总会有一个配置对象类存储你加载的配置项的值:Flask对象中的config属性就是干这事的。这里存储的是Flask特定配置项的值,也是扩展组件可以存储配置值的地方。当然,你也可以存储其他你所需的值。


1. 基础配置

        config是字典的一个子类,它可以像是字典那样进行修改值:

app = Flask(__name__)
app.config['DEBUG'] = True

        给定的配置值也会传递给Flask对象,因此你也可以用这种方式进行读或写:

app.debug = True

        为了一次性修改多个键值,你还可以使用dict.update()函数:

app.config.update(
    TESTING=True,
    SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/'
)


2. 环境和调试功能

        环境配置(ENV)和调试模式配置(DEBUG)这两个配置项比较特别,因为在应用程序开始建立之后,它们的行为可能与其值不一致。为了可靠地设置环境配置和调试模式配置,Flask使用了环境变量。

        环境配置被用来指示Flask、扩展组件以及其他程序,比如Sentry,Flask正在运行的上限文是什么。它由FLASK_ENV环境变量控制,并且默认为production。

        将FLASK_ENV设置为development,需要启用调试模式。flask run会在调试模式下使用交互调试器和重新加载器。为了将它从环境变量分离出来,使用的是FLASK_DEBUG标识。

        改变于版本1.0:添加FLASK_ENV来控制环境配置与调试模式配置分离。开发环境启用调试模式。

        为了将Flask转换到开发环境并且启用调试模式,设置FLASK_ENV:

$ export FLASK_ENV=development
$ flask run

        (在Windows操作系统,使用set替换export。)

        向上面描述的那样使用环境变量是推荐的方式。虽然可以在配置或者代码中设置环境配置(ENV)和调试模式配置(DEBUG),但我们并不推荐这样使用。因为这样做,这两个变量并不能在flask命令之前被读取到,并且有些系统或者扩展可能已经根据以前的值来配置它们。


3. 内置的配置项

        下面是Flask中使用的内置的配置项:

        ENV

                表示应用程序运行在什么环境上。Flask和扩展组件可能使基于环境的行为成为可能,比如启用调试模式。env属性映射到这个配置项。这是由Flask_ENV环境变量设置的,并且如果在代码中设置的话,表现的行为可能与预期值不符。

                不要在生产环境中将这个值设置为development。

                默认值:production

                新增于版本1.0。

        DEBUG

                启用或禁用调试模式。当使用flask run来启动开发服务器,一个交互调试器将启动并显示程序在运行过程中未处理的异常,并且当代码有变更时服务器会重新加载。debug属性映射到这个配置项。当ENV的值为development时,调试模式是开启的;并且这个值是由FLASK_DEBUG环境变量进行覆盖的。如果在代码中设置的话,其表现的行为可能与预期值不符。

                不要在生产环境中将这个值设置为development。

                默认值:True,如果ENV为development,这个值为False。

        TESTING

                开启测试模式。异常被传播,而不是由应用程序的错误处理程序进行处理。扩展组件也可能改变它们的行为,以便测试更加容易。你应该在你自己的测试中开启这个配置项。

                默认值:False

        PROPAGATE_EXCEPTIONS

                异常被重新抛出,而不是由应用程序的错误处理程序进行处理。如果没有设置,且TESTING或者DEBUG被开启了,那么这个配置项将被隐式地设置为true。

                默认值:None

        PRESERVE_CONTEXT_ON_EXCEPTION

                当有一个异常发生时,不会弹出请求上下文。如果没有设置,且DEBUG为true的话,那么这个配置项将被设置为true。这个配置项允许调试器对错误的请求数据进行内省,并且通常不需要直接设置。

                默认值:None

        TRAP_HTTP_EXCEPTIONS

                如果一个HTTPException类型的异常没有对应的处理程序,将重新抛出这个异常,并由交互式调试器进行处理,而不是将其作为一个简单的错误响应进行回执。

                默认值:False

        TRAP_BAD_REQUEST_ERRORS

                尝试访问一个不存在于请求字典中的键,比如args和form,将会返回一个400 Bad Request的错误页面。开启这个配置项将会把这个错误当做一个未处理的异常显示到交互式调试器中。这是一个TRAP_HTTP_EXCEPTIONS衍生的特别版本。如果没有设置,这个选项将在调试模式下开启。

                默认值:None

        SECRET_KEY

                表示一个密钥,它将用于安全地签署会话cookie,并且它能在你的应用程序中用于扩展组件中其他安全相关的需求。它应该是一个很长的随机字符串,尽管Unicode也能被接受。例如,拷贝下面的输出内容到你的配置中:

python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'

                在发布问题和提交代码的时候,不要透露这个密钥!

                默认值:None

        SESSION_COOKIE_NAME

                会话cookie的名称。可以在如下场景更改这个值:你已经拥有一个跟这个名字一模一样的cookie。

                默认值:‘session’

        SESSION_COOKIE_DOMAIN

                会话cookie将会生效的域匹配规则。如果设置为False,cookie的域将不会被设置。如果没有设置,cookie就会对SERVER_NAME的所有子域生效。

                默认值:None

        SESSION_COOKIE_PATH

                会话cookie将会生效的路径。如果没有设置,cookie会在APPLICATION_ROOT下生效,或者在/下生效(如果APPLICATION_ROOT没有设置的话)。

                默认值:None

        SESSION_COOKIE_HTTPONLY

                为了安全起见,浏览器将不会允许JavaScript访问被标记为“HTTP only”的cookie。

                默认值:True

        SESSION_COOKIE_SECURE

                如果cookie被标记为“secure”,那么浏览器将仅仅发送HTTPS请求的cookie。应用程序必须通过HTTPS工作,才会让这个配置项有意义。

                默认值:False

        SESSION_COOKIE_SAMESITE

                限制cookie是如何随着外部网站请求发送的。该配置项能够被设置为‘Lax’(推荐)或者‘Strict’。请查阅Set-Cookie options(后续会讲到)。

                默认值:None

                新增于版本1.0。

        PERMANENT_SESSION_LIFETIME

                如果session.permanent为true,那么cookie的过期时间将会被设置成几秒钟后。这个值类型既能设置为datetime.timedelta,也能设置为int。

                Flask的默认cookie执行将验证这个加密签名是否大于这个配置项的值。

                默认值:timedelta(days=31)(2678400秒)

        SESSION_REFRESH_EACH_REQUEST

                当session.permanent为true时,控制cookie是否随每个响应一起发送。一直发送cookie(默认行为)能让会话不容易过期,但是需要使用更多的带宽。非长期存在的会话不受这个配置项的影响。

                默认值:True

        USE_X_SENDFILE

                在服务文件时,设置X-Sendfile头而不是使用Flask来服务数据。有些web服务,比如Apache,意识到了这点,并且更加有效地服务数据。这个配置选项仅在使用这种服务器的时候有意义。

                默认值:False

        SEND_FILE_MAX_AGE_DEFAULT

                当服务文件时,设置控制缓存最大期限为指定的秒数。能设置为一个int类型的值,也能设置为一个datetime.timedelta类型的值。在应用程序或蓝图的每个文件基础上要重写此值的话,则使用get_send_file_max_age()函数。

                默认值:timedelta(hours=12)(43200秒)

        SERVER_NAME

                通知应用程序绑定的主机地址和端口。这是子域路由匹配支持所需的。

                如果设置了这个值,且SESSION_COOKIE_DOMAIN没有设置,那么这个配置项的值将被用于会话cookie域。现代Web浏览器不允许在没有“.”的情况下设置域的cookie。为了在本地使用域,需添加任何应该路由到应用程序到你的主机文件的名称。

127.0.0.1 localhost.dev

                如果设置了这个值,url_for会生成具有一个应用程序上下文(而不是请求上下文)的外部URL。

                默认值:None

        APPLICATION_ROOT

                通知应用程序,它在应用程序/Web服务器下的安装路径是什么。

                如果SESSION_COOKIE_PATH没有设置的话,这个配置项将被用于会话cookie路径。

                默认值:‘/’

        PREFERRED_URL_SCHEME

                当没有请求上下文时,使用此方案生成外部URL。

                默认值:‘http’

        MAX_CONTENT_LENGTH

                传入请求数据的最大字节数。如果没有设置这个配置项,且请求没有指定一个CONTENT_LENGTH,为了安全起见不会有数据被读取。

                默认值:None

        JSON_AS_ASCII

                将对象序列化为ASCII编码的JSON。如果这个配置项是不可用的,JSON会被当做一个Unicode字符串进行返回动作,或者使用jsonify将其编码为UTF-8。当在模板中将JSON渲染给JavaScript时,若不开启这个配置项是会带来安全相关的影响的,因此这个配置项默认是保持开启的。

                默认值:True

        JSON_SORT_KEYS

                以字母顺序对JSON对象的键进行排序。这对于缓存是很有用的,因为不管Python的哈希种子是什么,它都将确保数据以相同的方式进行序列化。虽然不推荐这样做,但是如果你想改进缓存成本的性能,你可以禁用这个配置项。

                默认值:True

        JSONIFY_PRETTYPRINT_REGULAR

                jsonify响应将输出新行、空格以及缩进排版,以便容易阅读。这个配置项在调试模式下总是开启的。

                默认值:False

        JSONIFY_MIMETYPE

                jsonify响应的mimetype。

                默认值:‘application/json’

        TEMPLATES_AUTO_RELOAD

                当模板有更改时将会重新加载模板。如果没有设置,它会在调试模式下开启。

                默认值:None

        EXPLAIN_TEMPLATE_LOADING

                日志调试信息追踪如何加载一个模板文件。这可以被用来指出为什么一个模板没有被加载,或者为什么加载了一个错误的模板文件。

                默认值:False

        MAX_COOKIE_SIZE

                cookie头的最大字节数。默认为4093。较大的cookie可能会被浏览器静默地忽略。设置为0,用于关闭这个报警。

        更改于版本1.0:LOGGER_NAME和LOGGER_HANDLER_POLICY被移除,查看上一章节获取更多关闭日志记录的配置信息。

        添加ENV来反射FLASK_ENV环境变量。

        添加SESSION_COOKIE_SAMESITE来控制会话cookie的SameSite选项。

        添加MAX_COOKIE_SIZE来控制Werkzeug产生的报警。

        关于SERVER_NAME的更多知识:

        SERVER_NAME用于子域名支持。因为Flask在没有知道实际服务器名称下无法猜测到子域名部分,如果你想要使用子域名,那么该选项是必须的。同时这也作用于会话cookie。

        请记住,不仅仅是Flask无法知道子域是什么,你的web浏览器同样也是这样。大多数现代web浏览器不允许服务器名不含有点的跨子域名cookie。所以如果你的服务器名是‘localhost’,那么你不能在‘localhost’和它的每个子域名下设置cookie。请选择一个合适的服务器名,比如‘myapplication.local’,并添加你想要的服务器名+子域名到你的主机配置或者建立一个本地绑定

        更改日志:

        0.11版本新增:

                SESSION_REFRESH_EACH_REQUEST,

                TEMPLATES_AUTO_RELOAD,

                LOGGER_HANDLER_POLICY,

                EXPLAIN_TEMPLATE_LOADING

        0.10版本新增:

                JSON_AS_ASCII,

                JSON_SORT_KEYS,

                JSONIFY_PRETTYPRINT_REGULAR

        0.9版本新增:

                PREFERRED_URL_SCHEME

        0.8版本新增:

                TRAP_BAD_REQUEST_ERRORS,

                TRAP_HTTP_EXCEPTIONS,

                APPLICATION_ROOT,

                SESSION_COOKIE_DOMAIN,

                SESSION_COOKIE_PATH,

                SESSION_COOKIE_HTTPONLY,

                SESSION_COOKIE_SECURE

        0.7版本新增:

                PROPAGATE_EXECPTIONS,

                PRESERVE_CONTEXT_ON_EXCEPTION

        0.6版本新增:

                MAX_CONTENT_LENGTH

        0.5版本新增:

                SERVER_NAME

        0.4版本新增:

                LOGGER_NAME


4. 从文件加载配置

        如果你将配置项存储到单独的文件中,那么配置项就显得更加有用了。在理想情况下,这个文件是位于实际应用程序包的外部的。通过各种不同的包处理工具(使用Setuptools部署,见快速入门章节)和最终修改配置文件,使得打包和分发应用程序成为可能。

        因此一个通用模式就像这样:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

        第一次加载配置来自于yourapplication.default_settings模块,随后加载YOURAPPLICATION_SETTINS环境变量指向的文件的内容来覆盖这些值。这个环境变量是在启动服务器之前,在Linux或者OS X操作系统上的shell中使用export命令设置的:

$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ python run-app.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader...

        在Windows操作系统,你需要使用内置的set命令:

>set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg

        这些配置文件实际上都是Python文件。只有大写的值稍后才会实际存储到config对象中。因此,你需要保证配置项的键一定是大写的。

        这里有一个配置文件的示例:

# Example configuration
DEBUG = False
SECRET_KEY = '?\xbf,\xb4\x8d\xa3"<\x9c\xb0@\x0f5\xab,w\xee\x8d$0\x13\x8b83'

        确定尽早加载配置,因为在启动程序的时候扩展组件也会访问这些配置。config对象还有其他方法也可以从独立的文件中加载数据。想要了解的话,请前往Config对象的介绍文档。


5. 从环境变量获取配置

        除了使用环境变量指向配置文件,你可能会发现,直接通过环境变量控制你的配置值是更加有用的(甚至必需的)。

        当服务器启动之前,环境变量可以在Linux或者OS X操作系统上,使用shell的export命令来设置:

$ export SECRET_KEY='5f352379324c22463451387a0aec5d2f'
$ export DEBUG=False
$ python run-app.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader...

        在Windows操作系统使用内置命令set代替export:

>set SECRET_KEY='5f352379324c22463451387a0aec5d2f'
>set DEBUG=False

        虽然使用这种方法很简单,但请记住,环境变量是字符串——它们不会自动反序列化为Python的类型。

        这里有一个使用环境变量的配置文件的示例:

# Example configuration
import os


ENVIRONMENT_DEBUG = os.environ.get("DEBUG", default=False)
if ENVIRONMENT_DEBUG.lower() in ("f", "false"):
    ENVIRONMENT_DEBUG = False

DEBUG = ENVIRONMENT_DEBUG
SECRET_KEY = os.environ.get("SECRET_KEY", default=None)
if not SECRET_KEY:
    raise ValueError("No secret key set for Flask application")

        注意,除了空字符串外,其他的字符串都会被解释为Python的bool值True,如果你想要使用False值,就将字符串置空。

        请确定应该很早就要完成加载配置的动作,这样在程序启动的时候,扩展就可以访问这些配置。这里还有其他方法同样也能让config对象从单独的文件加载数据。想要了解完整的内容,请前往Config类文档。


6. 配置的最佳实践

        前文所述的方法缺点在于,其使得测试变得困难。通常对于这个问题没有单一的100%解决方案,但是记住下面几点,有助于你提升经验:

        1. 在一个方法中创建你的应用,并在其中注册你的蓝图。这样做,你可以根据不同的配置为你的应用程序创建不同的实例对象,这样做可以让单元测试变得稍微简单点。你可以在需要的时候使用这种方式来传入配置。

        2. 不要在导入时写需要配置的代码。如果你限制只在请求中访问配置,你可以在之后按需求重新配置对象。


7. 开发/生产

        大多数应用程序需要不止一个的配置。它们至少需要一个生产服务器的配置和一个开发期间的配置。处理这儿的最简单办法是,使用一份默认的总会被加载的配置,和一部分版本控制,以及独立的配置进行必要的覆盖:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

        接着,你需要添加一个单独的config.py文件,并且export到环境变量中。然后,这里还可以使用其他方法,比如,使用导入或者子类。

        在Django中最流行的方式是,在你的config文件的顶部添加from yourapplication.default_settings import *进行显式地导入,然后手动更改你需要覆盖的值。你也可以检查你的环境变量,比如YOURAPPLICATION_MODE,将其设置为production,development等等,最后根据这个环境变量来导入不同的硬编码文件。

        比较有趣的一个模式是,使用配置类,并派生这个类:

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'

class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    TESTING = True

        要启用这样的配置,你仅需要调用from_object()

app.config.from_object('configmodule.ProductionConfig')

        这里讲解了许多不同的方法,但最终还是取决于你想如何管理你的配置文件。下面列出一些建议:

        ● 在版本控制中保留默认配置。要么使用此默认配置填充你的配置,要么在覆盖值之前将其导入到自己的配置文件中。

        ● 使用环境变量来切换到不同的配置。这可以在Pyton解释器的外部进行,使得开发和部署更加容易,因为你不用接触代码就可以快速且容易地切换到不同的配置。如果你经常在不同的项目中工作,你设置可以创建自己的脚本,用于激活一个虚拟环境以及导出开发环境的脚本。

        ● 在生产中,使用像fabric一样的工具来推送代码和配置到生产服务器(集群)。你可以前往Deploying with Fabric模式获取更多细节。


8. 实例文件夹

        (新增于版本0.8。)

        Flask0.8引进了实例文件夹。Flask在很长时间内都可以直接引用与应用程序文件夹相关的路径(通过Flask.root_path)。这也是为何很多开发者都喜欢将配置存储在应用程序所在目录下。不幸的是,这仅能在应用程序不是包(即根目录指向的是包的内容)的情况下才能有效工作。

        从Flask0.8版本开始引进了一个新的属性:Flask.instance_path。它指的是一个叫做“实例文件夹”的新概念。实例文件夹被设计成不受版本控制的,且是特定于部署的。这是一个放置运行时改变的文件或者配置文件的最佳位置。

        你可以在创建Flask应用程序时为实例文件夹显式地提供路径,你也可以让Flask自动检测实例文件夹的位置。对于显式配置路径,使用的是instance_path关键字参数:

app = Flask(__name__, instance_path='/path/to/instance/folder')

        请记住,提供的路径必须是绝对路径。

        如果没有提供instance_path参数,则会使用下列默认的位置:

        ● 未安装的模块:

/myapp.py
/instance

        ● 未安装的包:

/myapp
    /__init__.py
/instance

        ● 已安装的模块或包:

$PREFIX/lib/python2.X/site-packages/myapp
$PREFIX/var/myapp-instance

        $PREFIX是你的Python的安装前缀。可以是/usr或者你的虚拟环境的路径。你可以打印sys.prefix的值来确定前缀是什么。由于配置对象提供了从相对文件名加载配置文件的功能,如果有需要的话,我们可以通过与实例路径相对应的文件名来改变加载。配置文件中相对路径的行为可以通过应用程序构造函数的instance_relative_config关键字参数,在“相对应用程序的根目录”(默认为False)和“相对实例文件夹”之间进行切换。

app = Flask(__name__, instance_relative_config=True)

        这里有一个示例演示了怎样配置Flask从一个模块预加载配置,以及随后覆盖配置文件夹下的配置文件(如果存在)的情况:

app = Flask(__name__, instance_relative_config=True)
app.config.from_object('yourapplication.default_settings')
app.config.from_pyfile('application.cfg', silent=True)

        实例文件夹的路径可以通过Flask.instance_path找到。Flask也提供了一个打开实例文件夹中文件的快捷方式,即Flask.open_instance_resource(),示例如下:

filename = os.path.join(app.instance_path, 'application.cfg')
with open(filename) as f:
    config = f.read()

# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
    config = f.read()

猜你喜欢

转载自blog.csdn.net/regandu/article/details/80175021
今日推荐