librelist archives

« back to archive

Avoid reloader crashes with Flask-Failsafe

Avoid reloader crashes with Flask-Failsafe

From:
Matt Good
Date:
2012-09-15 @ 17:36
The one issue I have with the Flask reloader is that I frequently crash 
the dev server when I save in the middle of something. My incomplete code 
has a syntax error, so the initialization fails and the process just 
exits.

I've posted an extension that helps avoid this type of error from crashing
the dev server:

  http://pypi.python.org/pypi/Flask-Failsafe/

Usage looks like this:

  from flask_failsafe import failsafe

  @failsafe
  def create_app():
    # note that the import is *inside* this function so that we can catch
    # errors that happen at import time
    from myapp import app
    return app

  if __name__ == "__main__":
    create_app().run()


By wrapping the app factory with @failsafe, it will attempt to call 
create_app(), but if that fails it will return a dummy app that just 
displays the Flask exception debugger for that initialization error.

If there is an error initializing the app it also passes the files that 
were being imported at the time to the reloader to monitor for changes. 
Otherwise, since those files failed to import successfully, they would not
be in sys.modules, so the reloader would not monitor them.

I've had good luck with this so far, but I'm anxious for other people to 
try it out.

-- Matt 

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Simon Sapin
Date:
2012-09-17 @ 13:14
A brilliant solution to a long-standing annoyance with the Werkzeug 
reloader. Congrats :)

-- 
Simon Sapin

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Matt Good
Date:
2012-09-18 @ 21:38
On Sep 17, 2012, at 6:14 AM, Simon Sapin <simon.sapin@exyr.org> wrote:

> A brilliant solution to a long-standing annoyance with the Werkzeug 
> reloader. Congrats :)


Thanks, I'm glad other people are finding it useful.

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Cory Li
Date:
2012-09-20 @ 05:08
Another vote for this utility! Small syntax errors are no longer annoying.

-----Original Message-----
From: flask@librelist.com [mailto:flask@librelist.com] On Behalf Of Matt Good
Sent: Tuesday, September 18, 2012 2:38 PM
To: flask@librelist.com
Subject: Re: [flask] Avoid reloader crashes with Flask-Failsafe

On Sep 17, 2012, at 6:14 AM, Simon Sapin <simon.sapin@exyr.org> wrote:

> A brilliant solution to a long-standing annoyance with the Werkzeug 
> reloader. Congrats :)


Thanks, I'm glad other people are finding it useful.

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Steven Kryskalla
Date:
2012-09-15 @ 18:25
On Sat, Sep 15, 2012 at 10:36 AM, Matt Good <matt@matt-good.net> wrote:
> I've had good luck with this so far, but I'm anxious for other people to
try it out.

Just tested it, very nice!

I had a small problem where my app runner depended on a config value
that gets set in create_app. Since create_app didn't finish, that
config value wasn't set, and the runner died with a second exception.
I moved that code into create_app and now it's working fine.

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Joe Esposito
Date:
2012-09-16 @ 17:35
Clever! I like the fallback server containing the exception details. It's
definitely a pain to restart the server after compulsively saving after
each change. The only downside I can think of is now the failsafe is
exposed to production.

I wonder if Flask could actually solve this problem out-of-the-box. If the
'Flask' constructor took another argument indicating an additional factory
step, perhaps your README example <https://github.com/mgood/flask-failsafe> can
then look something like this:


from flask import Flask

def create_app(app):
  # initialize app here -- note that there is *no* import
  return app

app = Flask('myapp', factory=create_app)

if __name__ == '__main__':
  app.run()

This exposes 'app', as required for production environments, allowing *Flask
* to do the import and handle any import errors similar to your extension
when in development. The Manager class can be extended in the same way.

Anyone think this would be helpful?

On Sat, Sep 15, 2012 at 2:25 PM, Steven Kryskalla <skryskalla@gmail.com>wrote:

> On Sat, Sep 15, 2012 at 10:36 AM, Matt Good <matt@matt-good.net> wrote:
> > I've had good luck with this so far, but I'm anxious for other people to
> try it out.
>
> Just tested it, very nice!
>
> I had a small problem where my app runner depended on a config value
> that gets set in create_app. Since create_app didn't finish, that
> config value wasn't set, and the runner died with a second exception.
> I moved that code into create_app and now it's working fine.
>

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Matt Good
Date:
2012-09-18 @ 21:36
On Sep 16, 2012, at 10:35 AM, Joe Esposito <espo58@gmail.com> wrote:

> Clever! I like the fallback server containing the exception details. 
It's definitely a pain to restart the server after compulsively saving 
after each change. The only downside I can think of is now the failsafe is
exposed to production.


Thanks! However, I would recommend using separate scripts for dev and 
production. I have a small script that just starts the dev server and for 
production I use gunicorn.


> I wonder if Flask could actually solve this problem out-of-the-box. If 
the 'Flask' constructor took another argument indicating an additional 
factory step, perhaps your README example can then look something like 
this:
> 
> from flask import Flask
> 
> def create_app(app):
>   # initialize app here -- note that there is *no* import
>   return app
> 
> app = Flask('myapp', factory=create_app)
> 
> if __name__ == '__main__':
>   app.run()
> 
> This exposes 'app', as required for production environments, allowing 
Flask to do the import and handle any import errors similar to your 
extension when in development. The Manager class can be extended in the 
same way.
> 
> Anyone think this would be helpful?


I would love if Flask or the Werkzeug reloader handled this out-of-the-box.

However, we may have our apps laid out a bit differently. My code looks 
something like this:

server-develop:
    small script that imports and runs the app in dev mode

src/myapp/__init__.py:
    app = Flask(__name__)

The application and code are all defined under the "myapp" package. The 
server-develop script only contains the code to import "myapp.app" and run
it for development.

I'll have to reflect on your example a little bit more, but maybe this 
will spark some ideas for Armin on how he'd like to handle these startup 
errors.


> 
> On Sat, Sep 15, 2012 at 2:25 PM, Steven Kryskalla <skryskalla@gmail.com> wrote:
> On Sat, Sep 15, 2012 at 10:36 AM, Matt Good <matt@matt-good.net> wrote:
> > I've had good luck with this so far, but I'm anxious for other people 
to try it out.
> 
> Just tested it, very nice!
> 
> I had a small problem where my app runner depended on a config value
> that gets set in create_app. Since create_app didn't finish, that
> config value wasn't set, and the runner died with a second exception.
> I moved that code into create_app and now it's working fine.
> 

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Dmitry Medvinsky
Date:
2012-09-20 @ 11:40
Looks awesome.

Just installed it and included in one of the projects. Was as simple
as adding an import and modifying a single line in my `manage.py`
file:

- app = create_app()
+ app = failsafe(create_app)()

Production server isn't using manage.py, so nothing is decorated in production.

Everything works so far; I'll post if something breaks.

Thanks, Matt!


On Sat, Sep 15, 2012 at 9:36 PM, Matt Good <matt@matt-good.net> wrote:
> The one issue I have with the Flask reloader is that I frequently crash 
the dev server when I save in the middle of something. My incomplete code 
has a syntax error, so the initialization fails and the process just 
exits.
>
> I've posted an extension that helps avoid this type of error from 
crashing the dev server:
>
>   http://pypi.python.org/pypi/Flask-Failsafe/
>
> Usage looks like this:
>
>   from flask_failsafe import failsafe
>
>   @failsafe
>   def create_app():
>     # note that the import is *inside* this function so that we can catch
>     # errors that happen at import time
>     from myapp import app
>     return app
>
>   if __name__ == "__main__":
>     create_app().run()
>
>
> By wrapping the app factory with @failsafe, it will attempt to call 
create_app(), but if that fails it will return a dummy app that just 
displays the Flask exception debugger for that initialization error.
>
> If there is an error initializing the app it also passes the files that 
were being imported at the time to the reloader to monitor for changes. 
Otherwise, since those files failed to import successfully, they would not
be in sys.modules, so the reloader would not monitor them.
>
> I've had good luck with this so far, but I'm anxious for other people to
try it out.
>
> -- Matt
>
>

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Sean Lynch
Date:
2012-09-20 @ 13:57
Works great.  Nice work Matt.

On Thu, Sep 20, 2012 at 7:40 AM, Dmitry Medvinsky <dmedvinsky@gmail.com>wrote:

> Looks awesome.
>
> Just installed it and included in one of the projects. Was as simple
> as adding an import and modifying a single line in my `manage.py`
> file:
>
> - app = create_app()
> + app = failsafe(create_app)()
>
> Production server isn't using manage.py, so nothing is decorated in
> production.
>
> Everything works so far; I'll post if something breaks.
>
> Thanks, Matt!
>
>
> On Sat, Sep 15, 2012 at 9:36 PM, Matt Good <matt@matt-good.net> wrote:
> > The one issue I have with the Flask reloader is that I frequently crash
> the dev server when I save in the middle of something. My incomplete code
> has a syntax error, so the initialization fails and the process just exits.
> >
> > I've posted an extension that helps avoid this type of error from
> crashing the dev server:
> >
> >   http://pypi.python.org/pypi/Flask-Failsafe/
> >
> > Usage looks like this:
> >
> >   from flask_failsafe import failsafe
> >
> >   @failsafe
> >   def create_app():
> >     # note that the import is *inside* this function so that we can catch
> >     # errors that happen at import time
> >     from myapp import app
> >     return app
> >
> >   if __name__ == "__main__":
> >     create_app().run()
> >
> >
> > By wrapping the app factory with @failsafe, it will attempt to call
> create_app(), but if that fails it will return a dummy app that just
> displays the Flask exception debugger for that initialization error.
> >
> > If there is an error initializing the app it also passes the files that
> were being imported at the time to the reloader to monitor for changes.
> Otherwise, since those files failed to import successfully, they would not
> be in sys.modules, so the reloader would not monitor them.
> >
> > I've had good luck with this so far, but I'm anxious for other people to
> try it out.
> >
> > -- Matt
> >
> >
>

Re: [flask] Avoid reloader crashes with Flask-Failsafe

From:
Sean Lynch
Date:
2012-09-20 @ 13:59
Btw, I wrapped mine when creating the Manager instance so not to affect the
global create_app

> manager = Manager(failsafe(create_app))


On Thu, Sep 20, 2012 at 9:57 AM, Sean Lynch <techniq35@gmail.com> wrote:

> Works great.  Nice work Matt.
>
>
> On Thu, Sep 20, 2012 at 7:40 AM, Dmitry Medvinsky <dmedvinsky@gmail.com>wrote:
>
>> Looks awesome.
>>
>> Just installed it and included in one of the projects. Was as simple
>> as adding an import and modifying a single line in my `manage.py`
>> file:
>>
>> - app = create_app()
>> + app = failsafe(create_app)()
>>
>> Production server isn't using manage.py, so nothing is decorated in
>> production.
>>
>> Everything works so far; I'll post if something breaks.
>>
>> Thanks, Matt!
>>
>>
>> On Sat, Sep 15, 2012 at 9:36 PM, Matt Good <matt@matt-good.net> wrote:
>> > The one issue I have with the Flask reloader is that I frequently crash
>> the dev server when I save in the middle of something. My incomplete code
>> has a syntax error, so the initialization fails and the process just exits.
>> >
>> > I've posted an extension that helps avoid this type of error from
>> crashing the dev server:
>> >
>> >   http://pypi.python.org/pypi/Flask-Failsafe/
>> >
>> > Usage looks like this:
>> >
>> >   from flask_failsafe import failsafe
>> >
>> >   @failsafe
>> >   def create_app():
>> >     # note that the import is *inside* this function so that we can
>> catch
>> >     # errors that happen at import time
>> >     from myapp import app
>> >     return app
>> >
>> >   if __name__ == "__main__":
>> >     create_app().run()
>> >
>> >
>> > By wrapping the app factory with @failsafe, it will attempt to call
>> create_app(), but if that fails it will return a dummy app that just
>> displays the Flask exception debugger for that initialization error.
>> >
>> > If there is an error initializing the app it also passes the files that
>> were being imported at the time to the reloader to monitor for changes.
>> Otherwise, since those files failed to import successfully, they would not
>> be in sys.modules, so the reloader would not monitor them.
>> >
>> > I've had good luck with this so far, but I'm anxious for other people
>> to try it out.
>> >
>> > -- Matt
>> >
>> >
>>
>
>