最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Flask本地和线上用gunicorn和supervisor部署时如何传入环境变量

Flask crifan 288浏览 0评论
折腾:
【已解决】Flask中如何利用环境变量实现自动加载开发还是生产的配置
后,需要去在线上环境,或者本地模拟的环境,去部署时,如何传入环境变量的值。
此处部署用的是gunicorn和supervisor
之前的部署的配置是:
conf/gunicorn/gunicorn_config.py
import multiprocessing
import os
import sys
sys.path.append(".")
from config import BaseConfig

#currentRootPath = "/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo"
currentRootPath = os.getcwd()
print("currentRootPath=%s" % currentRootPath)
flaskHost = BaseConfig.FLASK_HOST
flaskPort = BaseConfig.FLASK_PORT
print("flaskHost=%s, flaskPort=%s" % (flaskHost, flaskPort))


reload = True                                   #当代码改变时自动重启服务
#bind = '127.0.0.1:32851'                        #绑定ip和端口号
# bind = '0.0.0.0:32851'                        #绑定ip和端口号
bind = ("%s:%s" % (flaskHost, flaskPort))
backlog = 512                                   #监听队列
chdir = currentRootPath                         #gunicorn要切换到的目的工作目录
timeout = 30                                    #超时
worker_class = 'sync'                           #默认的是sync模式
workers = multiprocessing.cpu_count() * 2 + 1   #进程数
threads = 2                                     #指定每个进程开启的线程数
loglevel = 'info'                               #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'    #设置gunicorn访问日志格式,错误日志无法设置
"""
其每个选项的含义如下:
h          remote address
l          '-'
u          currently '-', may be user name in future releases
t          date of the request
r          status line (e.g. ``GET / HTTP/1.1``)
s          status
b          response length or '-'
f          referer
a          user agent
T          request time in seconds
D          request time in microseconds
L          request time in decimal seconds
p          process ID
"""

accesslog = currentRootPath + "/logs/gunicorn_access.log"      #访问日志文件
errorlog  = currentRootPath + "/logs/gunicorn_error.log"       #错误日志文件
conf/supervisor/supervisord_server.conf
[program:robotDemo]
command=/Users/crifan/.local/share/virtualenvs/robotDemo-HXjMJQEQ/bin/gunicorn -c gunicorn_config.py app:app
;user=root
directory=/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo
感觉像是:
直接在:
gunicorn -c gunicorn_config.py app:app
传入参数:
FLASK_ENV=production
变成:
gunicorn -c gunicorn_config.py  FLASK_ENV=production app:app
就可以了?
还是要去搜搜看
python gunicorn supervisor pass environment
shell – How to use environment variables with supervisor, gunicorn and django (1.6) – Stack Overflow
好像也可以直接放到:
gunicorn.py
中?
去PyCharm中试试
脚本路径:
/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn
参数:
-c conf/gunicorn/gunicorn_config.py app:app
环境变量:
PYTHONUNBUFFERED=1;FLASK_ENV=production
看看能否正常调试进入Flask的代码
是可以检测到环境变量的:
/Users/crifan/.virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/python /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py --multiproc --qt-support=auto --client 127.0.0.1 --port 61063 --file /Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c conf/gunicorn/gunicorn_config.py app:app
pydev debugger: process 53780 is connecting

Connected to pydev debugger (build 181.5087.37)
curPath=/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo/server/xxxRobotDemoServer/conf/gunicorn
confPath=/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo/server/xxxRobotDemoServer/conf/gunicorn/..
Before load .env: DEBUG=False, MONGODB_HOST=localhost, FILE_URL_HOST=127.0.0.1
cur_flask_environ=production
FLASK_ENV=production
但是运行会出现警告:
objc[53869]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[53875]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
但是后续好像又可以继续执行的样子:
不过总之使得PyCharm调试很卡,估计是耗费资源太多。
先去改为:
supervsior的ini中设置
environment=SECRET_KEY=”my_secret_key”
这种设置方法
python – Get environment variable in Supervisor – Stack Overflow
python – Set environment variables with supervisor for Flask – Stack Overflow
python – Flask not reading environment variables with supervisor, gunicorn and nginx – Stack Overflow
flask set environment in  gunicorn supervisor
flask 设置环境变量   gunicorn supervisor
python 3.x – Activating Gunicorn through virtualenv with Supervisor for Flask Application – Stack Overflow
python – Flask behind gunicorn and supervisor – log all requests and responses – Stack Overflow
supervisor+gunicorn部署python web项目 – CSDN博客
; 可以通过 environment 来添加需要的环境变量,一种常见的用法是修改 PYTHONPATH
; environment=PYTHONPATH=$PYTHONPATH:/path/to/somewhere
python 部署:virtuale + gunicorn + supervisor + flask – 小梦龙的个人页面 – 开源中国
flask pass environment
python – How I can pass environment variables to my flask application – Stack Overflow
python – Env. Variables not set while running Minimal Flask application – Stack Overflow
apache – cannot get environment variables set in Flask application – Stack Overflow
brettlangdon/flask-env: Easily set Flask settings from environment variables
算了,此处先去试试:
gunicorn中直接加上:
FLASK_ENV=production
变成:
conf/supervisor/supervisord_local.conf
[program:robotDemo]
;command=/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c gunicorn_config.py app:app
command=/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c gunicorn_config.py FLASK_ENV=production app:app
然后再去搞清楚:
Mac本地如何启动supervisor:
【已解决】Mac本地用supervisor和gunicorn启动和管理Flask的app
然后发现
command=/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c conf/gunicorn/gunicorn_config.py FLASK_ENV=production app:app
是没有传入进去的:
同时后来也看到了:
logs/gunicorn_error.log
中还会提示找不到这个模块:
[2018-08-22 14:50:31 +0800] [55903] [INFO] Booting worker with pid: 55903
[2018-08-22 14:50:31 +0800] [55903] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
    worker.init_process()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/workers/gthread.py", line 104, in init_process
    super(ThreadWorker, self).init_process()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/workers/base.py", line 129, in init_process
    self.load_wsgi()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
    return self.load_wsgiapp()
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/lib/python3.6/site-packages/gunicorn/util.py", line 350, in import_app
    __import__(module)
ModuleNotFoundError: No module named 'FLASK_ENV=production'
所以去改为:
supervisor environment
Configuration File — Supervisor 3.3.4 documentation
使用 supervisor 管理进程 – 李林克斯
supervisor can’t get linux environment variable · Issue #1044 · Supervisor/supervisor
“environment
A list of key/value pairs in the form KEY=”val”,KEY2=”val2″ that will be placed in the supervisordprocess’ environment (and as a result in all of its child process’ environments). This option can include the value %(here)s, which expands to the directory in which the supervisord configuration file was found. Values containing non-alphanumeric characters should be quoted (e.g. KEY=”val:123″,KEY2=”val,456″). Otherwise, quoting the values is optional but recommended. To escape percent characters, simply use two. (e.g. URI=”/first%%20name”) Note that subprocesses will inherit the environment variables of the shell used to start supervisord except for the ones overridden here and within the program’s environment option. See Subprocess Environment.
Default: no values
Required: No.
Introduced: 3.0″
推荐用引号,所以虽然可以写成:
environment = FLASK_ENV=production
但最好写成:
environment = FLASK_ENV="production"
然后去运行看看效果。
然后是可以传入环境变量的:
supervisord -c conf/supervisor/supervisord_local.conf
->
Before load .env: DEBUG=False, MONGODB_HOST=localhost, FILE_URL_HOST=127.0.0.1
cur_flask_environ=production
FLASK_ENV=production
cur_dir=/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo/server/xxxRobotDemoServer/conf/app
env_folder=production
dotenv_path=/Users/crifan/dev/dev_root/company/xxx/projects/robotDemo/server/xxxRobotDemoServer/conf/app/production/.env
dotenv_load_ok=True
After  load .env: DEBUG=True, MONGODB_HOST=localhost, FILE_URL_HOST=47.x.x.x
【总结】
此处可以通过:
conf/supervisor/supervisord_local.conf
[program:robotDemo]
;command=/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c gunicorn_config.py app:app
command=/Users/crifan/.local/share/virtualenvs/xxxRobotDemoServer-SCpLPEyZ/bin/gunicorn -c conf/gunicorn/gunicorn_config.py app:app
environment = FLASK_ENV="production"
;environment = FLASK_ENV="development"
去传入
FLASK_ENV=”production”
或:
FLASK_ENV=”development”
然后代码中用:
cur_flask_environ = os.getenv("FLASK_ENV")
即可得到:”production”或”development”,实现了把环境变量参数从supervisord中传入Flask的app中。
但是又出现其他问题:
【未解决】Mac中本地用supervidord部署运行Flask的app但经常退出无法稳定运行

转载请注明:在路上 » 【已解决】Flask本地和线上用gunicorn和supervisor部署时如何传入环境变量

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
88 queries in 0.131 seconds, using 20.66MB memory