在Windows中为Flask应用程序导出环境变量

时间:2019-07-16 18:41:38

标签: python flask environment-variables factory

我正在关注功能完整的Youtube教程Web应用程序,而应用程序工厂存在问题。根据我的理解,我需要将诸如SECRET_KEY和SQLALCHEMY_DATABASE_URI之类的敏感信息放入环境变量中。在视频中,创建者正在Mac上工作,他打开了.bash_profile文件并添加了以下几行(我将实际值留空):

export SECRET_KEY='....'
export SQLALCHEMY_DATABASE_URI='......'

我正在使用Windows,但无法在计算机中找到.bash_profile文件,因此我转到控制面板并设置了新的环境变量SECRET_KEY和SQLALCHEMY_DATABASE_URI。然后,像在视频中一样,在config.py

中创建此类Config
class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY')
    SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI')
    MAIL_SERVER = 'smtp.gmail.com'
    MAIL_PORT = 587
    MAIL_USE_TLS = True
    MAIL_USERNAME = os.environ.get('EMAIL_USER')
    MAIL_PASSWORD = os.environ.get('EMAIL_PASSWORD')

然后,我运行了我的应用程序,但出现了一条错误消息“必须使用密钥才能使用CSRF。”,所以我认为我的flask应用程序无法获取我设置的SECRET_KEY或其他环境变量。在我在 init .py中拥有这些配置之前,该应用程序运行良好,但是现在,当我将这些配置移至config.py中的对象内部时,它停止运行。

根据我的理解,export是创建环境变量的命令,因此我认为在.bash_profile文件中导出这些变量等同于设置环境变量。

为解决我的问题,我尝试通过创建.env文件来遵循本教程(https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xv-a-better-application-structure)。在命令提示符下,我运行了

 pip install python-dotenv

在Config.py中,我添加了

from dotenv import load_dotenv

basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))

我以为这会创建一个.env文件,我可以在其中存储环境变量,但是它什么也没做,因此我在目录中看不到任何.env文件。有人可以帮帮我吗 ?我有几个问题:

  1. 我需要添加/修复哪些内容才能使应用程序正常工作?

  2. 是否设置环境变量并将其导出为相同?如果没有,在设置环境变量后如何导出环境变量,以便我的应用程序可以正常工作?

  3. 在.env文件中存储环境变量与在“控制面板”中设置环境变量有何不同?因为当我尝试在Google上搜索“在Windows中编辑.env文件”时,出现了“添加环境变量”之类的结果。

  4. .bash_profile和.env文件有什么区别?我运行了man bash,它说.bash_profile是The personal initialization file, executed for login shells,但是我不知道这是否意味着它与.env文件完全不同。

1 个答案:

答案 0 :(得分:1)

设置环境变量的问题 从控制面板是用于程序检测 这些变量中的更改需要关闭并重新打开。 但是,当您运行程序时,它会继承环境变量 从其父进程。因此,您也需要关闭它,然后一直进行到explorer.exe。所以有点棘手。

所以您需要采用其他方法。

1。从命令行设置环境变量:

您可以为命令行会话设置环境变量 在Windows上使用set命令 (export在Windows上不存在。

set "SECRET_KEY=really secret don't tell anyone"

然后检查它是否真的设置了:

echo %SECRET_KEY%

应打印really secret don't tell anyone。或者,您可以只使用set命令而不带任何参数,这将打印所有环境变量。

以这种方式设置所有环境变量后,运行您的应用程序:

# app.py
from flask import Flask
import config

app = Flask(__name__)
@app.route('/')
def home():
    return 'secret is ' + config.SECRET_KEY

app.run()
# config.py
from os import getenv

SECRET_KEY = getenv('SECRET_KEY', None)
assert SECRET_KEY  # make sure app doesn't run without this value

运行它:

python config.py

输出:

really secret don't tell anyone

现在您可以从其他文件中导入config.py

要注意的一件事是,一旦关闭该cmd窗口, 这些环境值将未设置。 因此,如果打开新的命令行窗口,则需要重新输入它们。 或者,您可以在“控制面板”中设置值,然后新的cmd窗口会自动继承这些值(类似于.bashrc文件)。

使用.env文件

另一种方法是在项目的根文件夹中创建一个.env文件, 这是一个格式如下的文本文件

SECRET_KEY=really secret dont tell anyone
SQLALCHEMY_DATABASE_URI=sqlite:///app.db

文件夹结构:

.
├── .env
├── config.py
├── app.py

您必须不提交,并且必须这样做 与其他源文件一起共享这些.env文件。 因为这样在源代码中不对配置进行硬编码有什么意义,对吧?

要导入这些值,您需要对其进行解析并将其注入到应用程序环境中。 对于Python,您可以使用python-dotenv库。

现在我们可以将config.py更改为:

# config.py
from os import getenv

from dotenv import load_dotenv

load_dotenv()

SECRET_KEY = getenv('SECRET_KEY', None)
assert SECRET_KEY

# use the key
print(SECRET_KEY)

这将使我们能够从两个.env文件中加载配置 以及环境变量。

一种常见的模式是使用未填充的键制作一个.env.sample文件,以提醒管理员正在设置应用程序以填充这些值。

# .env.sample
SECRET_KEY=
SQLALCHEMY_DATABASE_URI=

现在,关于您的问题:

  

正在设置环境变量并将其导出   相同 ?如果没有,如何导出环境变量   设置环境变量后,我的应用程序可以工作吗?

“导出”环境变量与从控制面板进行设置相同。 两种方法都是从源代码中删除机密的方法。我已经在上面解释了两种方法来使您的应用程序正常工作。

  

在.env文件中存储环境变量与在“控制面板”中设置环境变量有何不同?因为当我尝试在Google上搜索“在Windows中编辑.env文件”时,会出现诸如“添加环境变量”之类的结果。

.env文件中存储环境变量有点容易出错,因为服务器配置错误很小, 您可能会向所有人公开这些秘密。 通过用set / export设置它们,您可以关闭该漏洞(如果黑客设法接管了您的应用程序,则仍然可以获取这些漏洞,因为如果您注意到我们可以使用{{ 1}}函数)。

  

.bash_profile和.env文件有什么区别?我运行了man bash,它说.bash_profile是为登录shell执行的个人初始化文件,但是我不知道这是否意味着它与.env文件完全不同。

Bash是UNIX系统中流行的shell应用程序。 getenv是每次您打开终端时都会执行的文件。 因此,当您向其中添加.bashrc命令时,打开的每个终端都将有效地设置那些环境变量。