我的目标是在Flask应用程序启动后运行任意代码.这是我得到的:
def run():
from webapp import app
app.run(debug=True, use_reloader=False)
Run Code Online (Sandbox Code Playgroud)
理想情况下,我可以这样做:
def run():
from webapp import app
app.run(debug=True, use_reloader=False)
some_code()
Run Code Online (Sandbox Code Playgroud)
但代码不会继续app.run(),所以some_code()永远不会运行.
我目前正在处理的解决方案是在app.run()的一个单独的线程中运行some_code(),创建一个先设置它的第一个请求函数:
app.is_running = True
Run Code Online (Sandbox Code Playgroud)
然后获取some_code()以向app发送基本请求,以便"在第一次请求之前"代码运行.这相当复杂,难以记录.我宁愿使用已经在Flask中提供的app.is_running参数,或者使用@app.after_server_start装饰器,但据我所知,这些都不存在.
帮我改进这段代码?
遗腹:每当我想到这个问题,它都会让我希望@app.after_server_start装饰品存在.
是否可以在第一次请求之前运行一个函数blueprint?
@my_blueprint.before_first_request
def init_my_blueprint():
print 'yes'
Run Code Online (Sandbox Code Playgroud)
目前,这将产生以下错误:
AttributeError: 'Blueprint' object has no attribute 'before_first_request'
Run Code Online (Sandbox Code Playgroud) 我使用app工厂模式定义我的Flask应用程序.使用Flask-Script时,我可以将工厂函数传递给Manager.我想改用Flask的内置Click CLI.如何使用Click工厂?
我当前的代码使用Flask-Script.如何使用Click执行此操作?
from flask import Flask
from flask_script import Manager, Shell
def create_app():
app = Flask(__name__)
...
return app
manager = Manager(create_app)
def make_shell_context():
return dict(app=app, db=db, User=User, Role=Role)
manager.add_command('shell', Shell(make_context=make_shell_context))
if __name__ == '__main__':
manager.run()
Run Code Online (Sandbox Code Playgroud) python command-line-interface flask flask-script python-click
传统上,我已将UWSGI配置文件配置为调用如下应用程序:
mydirectory/uwsgi_application.ini
...
#python module to import
app = run_web
module = %(app)
callable = app
...
Run Code Online (Sandbox Code Playgroud)
,
mydirectory/run_web.py
from ersapp import app
if __name__ == "__main__":
app.run()
Run Code Online (Sandbox Code Playgroud)
,
mydirectory/ersapp/__init__.py
...
app = Flask('ersapp')
...
Run Code Online (Sandbox Code Playgroud)
但现在,我正在关注Miguel Grinberg的Flask书,他在这里使用了如下的应用工厂
mydirectory/ersapp/__init__.py
...
def create_app(config_name):
webapp = Flask(__name__)
...
return webapp
Run Code Online (Sandbox Code Playgroud)
用"经理"(参见flask-script Manager)
mydirectory/manage.py
from webapp import create_app
...
webapp = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(webapp)
...
if __name__ == '__main__':
manager.run()
Run Code Online (Sandbox Code Playgroud)
在这个配置中,我用我的触发器来触发 $ python manage.py runserver
而在我触发它之前 $ python run_web.py …
我正在构建烧瓶应用程序并且这次决定尝试应用工厂方法,但是遇到了烧瓶迁移的麻烦并且无法找出简单的解决方案.
请注意,我想将配置位置作为脚本的选项传递
manage.py:
manager = Manager(create_app)
manager.add_option("-c", "--config", dest="config_module", required=False)
Run Code Online (Sandbox Code Playgroud)
然后我需要创建迁移实例并向管理器添加命令:
with manager.app.app_context():
migrate = Migrate(current_app, db)
manager.add_command('db', MigrateCommand)
Run Code Online (Sandbox Code Playgroud)
但是还没有创建应用实例,所以它失败了
我知道我可以在环境变量中传递config并在创建管理器实例之前创建应用程序,但是如何使用管理器选项呢?
使用我的应用程序,我使用flask-script和flask-migrate进行数据库迁移,一切都在本地运行.什么时候,我跑
heroku run python manage.py db init
Run Code Online (Sandbox Code Playgroud)
它创建了这个输出:
Running python manage.py db init on ? fpds-scheduler... up, run.1290 (Free)
Creating directory /app/migrations ... done
Creating directory /app/migrations/versions ... done
Generating /app/migrations/README ... done
Generating /app/migrations/script.py.mako ... done
Generating /app/migrations/alembic.ini ... done
Generating /app/migrations/env.py ... done
Please edit configuration/connection/logging settings in '/app/migrations/alembic.ini' before
proceeding.
Run Code Online (Sandbox Code Playgroud)
但是当我跑步时,heroku run python manage.py db migrate我得到一个错误
alembic.util.exc.CommandError: Path doesn't exist: 'migrations'. Please use the 'init' command to create a new scripts folder.
Run Code Online (Sandbox Code Playgroud)
当我运行heroku run …
有没有一种方法(在uWSGI或Flask中)注册一个函数,以便在每个worker生成后尽快运行?
我们有一个 Flask 应用程序,它可以从预加载一堆东西中受益。以下仅对preload8 个工作进程调用一次。第一个请求很快,但预加载的对象以某种方式共享,这会导致错误。
app = Flask(__name__)
preload()
Run Code Online (Sandbox Code Playgroud)
如果我使用before_first_request,那么对象会在每个工作进程中加载,并且不会出现错误,但第一个请求非常慢。
app = Flask(__name__)
@app.before_first_request
def bfr():
preload()
Run Code Online (Sandbox Code Playgroud)
我还尝试设置一个烧瓶脚本。运行该命令可以工作,但显然对象是在命令的进程中加载的,而不是在 uwsgi 工作线程中加载的。
app = Flask(__name__)
manager = Manager(app)
@manager.command
def preload():
...
Run Code Online (Sandbox Code Playgroud)
我想如果我们使用before_first_request,我们可以在重新启动 uwsgi 后手动触发请求。这是唯一的解决方案吗?
编辑:刚刚找到了 uswgi hook-post-fork选项(以及其他钩子选项)。明天我要尝试一下。也许其中之一就是我所需要的。
我正在使用应用程序工厂方法创建一个烧瓶应用程序,但在使用带有socketio和flask-script的Flask-Migrate时出现问题.
问题是我将我的create_app功能传递给了Manager我,但我也需要传递app给我socketio.run().而现在我似乎无法找到解决方案.有什么方法可以将这两种解决方案结合起来吗?
manage.py:
#app = create_app(False) <--- Old approach
#manager = flask_script.Manager(app)
manager = flask_script.Manager(create_app)
manager.add_option("-t", "--testing", dest="testing", required=False)
manager.add_command("run", socketio.run(
app,
host='127.0.0.1',
port=5000,
use_reloader=False)
)
# DB Management
manager.add_command("db", flask_migrate.MigrateCommand)
Run Code Online (Sandbox Code Playgroud)
当我使用旧的方法与socketio,但没有烧瓶 - 迁移一切工作.如果我使用新方法,并删除socketio部分,迁移工作.
注意:我希望能够使用以下两个命令调用我的应用程序.
python manage.py run
python manage.py -t True db upgrade
编辑:
试着用current_app我的意思RuntimeError: working outside of application context
manager.add_command("run", socketio.run(
flask.current_app,
host='127.0.0.1',
port=5000,
use_reloader=False)
)
Run Code Online (Sandbox Code Playgroud) 我正在尝试从Flask-Script manager.com中访问当前的应用程序实例.
这个错误输出(url_map是flask.app的属性)
@manager.command
def my_function():
x = app.url_map # this fails, because app is a callable
print "hi"
Run Code Online (Sandbox Code Playgroud)
这有效,但我不喜欢在app旁边添加parens.
@manager.command
def my_function():
x = app().url_map
print "hi"
Run Code Online (Sandbox Code Playgroud)
调试器显示app是可调用的.这与我正在创建应用程序实例的方式有关.我遵循这种模式:
def create_app(settings=None, app_name=None, blueprints=None):
...lots of stuff...
app = flask.Flask(app_name)
...lots of stuff...
return app
def create_manager(app):
manager = Manager(app)
@manager.command
def my_function():
x = app.url_map
print "hi"
def main():
manager = create_manager(create_app)
manager.run()
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
来自flask-script的文档说明了app参数Manager(app):
app - Flask实例,或者可调用返回Flask实例.
我很乐意在那里放一个可赎回的人,因为医生说这没关系.:-)而且我见过别人这样做.
但是现在我有这个我要添加的外围命令,这迫使我使用带有parens的应用程序并且闻起来有些错误.我究竟做错了什么?
编辑 …
flask ×10
flask-script ×10
python ×7
uwsgi ×2
heroku ×1
pymongo ×1
python-click ×1
virtualenv ×1