折腾:
【已解决】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”
这种设置方法
flask set environment in gunicorn supervisor
flask 设置环境变量 gunicorn supervisor
; 可以通过 environment 来添加需要的环境变量,一种常见的用法是修改 PYTHONPATH
; environment=PYTHONPATH=$PYTHONPATH:/path/to/somewhere
flask pass environment
算了,此处先去试试:
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
“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但经常退出无法稳定运行