How to implement event handling in Python Flask - python

Is there a canonical way in Python, and better yet in Flask, to implement an embedded event handling system?
With event handling, we mean something similar to Symfony's EventDispatcher, which is a simple, embedded system to decouple event dispatch and handling.
The goal is, in a Flask SQLAlchemy API App, to react to creation (or modification) of data objects with creation of additional, derived data objects to maintain a certain sense of consistency. There should be various handlers, each making sure that a certain type of consistency is maintained. These should be separated. It is possible that a handler triggers creation of data, which in turn prompts another handler to create data. This chain should be executed within the context of each request.
These are the options I came across, plus the reasons I ruled them out:
Flask signals - discourage us to manipulate data
Pyee - this seems closest to what we need, but not sure how well it integrated with Flask
Celery - seems more suited for async long running tasks
Whistle - one of many shots at the topic that don't seem exceptionally well maintained
RabbitMQ, ironMQ or similar - We would like to handle everything within the Flask app

Related

Architecturing an ML API in Django

I work on a project for our clients which is heavily ML based and is computationally intensive (as in complex and multi-level similarity scores, NLP, etc.) For the prototype, we delivered a Django RF where the API would have access to a database from the client and with every request at specific end-points it would literally do all the ML applications on the fly (in the backend).
Now that we are scaling and more user activity is taking place in the production, the app seems to lag a lot. A simple profiling shows that a single POST request could take upto 20 secs to respond. So no matter how much I optimize in terms of horizontal scaling, I can't get rid of the bottleneck of all the calculations happening with the API calls. I have a hunch that caching could be a kind of solution. But I am not sure. I can imagine a lot of 'theoretical' solutions but I don't want to reinvent the wheel (or shall I say, re-discover the wheel).
Are there specific design architectures for ML or computationally intensive REST API calls that I can refer to in redesigning my project?
Machine learning & natural language processing systems are often resource-hungry and in many cases there is not much one can do about it directly. Some operations simply take longer than others but this is actually not the main problem in your case. The main problem is that the user doesn't get any feedback while the backend does its job which is not a good user experience.
Therefore, it is not recommended to perform resource-heavy computation within the traditional HTTP request-response cycle. Instead of calling the ML logic within the API view and waiting for it to finish, consider setting up an asychronous task queue to perform the heavy lifting independently of the synchronous request-response cycle.
In the context of Django, the standard task queue implementation would be Celery. Setting it put will require some learning and additional infrastructure (e.g. a Redis instance and worker servers), but there is really no other way to not to break the user experience.
Once you have set up everything, you can then start an asynchronous task whenever your API endpoint receives a request and immediately inform the user that their request is being carried out via a normal view response. Once the ML task has finished and its results have been written to the database (using a Django model, of course), you can then notify the user (e.g. via mail or directly in the browser via WebSockets) to view the analysis results in a dedicated results view.

Django Process Lifetime

When using Django, how long does the Python process used to service requests stay alive? Obviously, a given Python process services an entire request, but is it guaranteed to survive across across requests?
The reason I ask is that I perform some expensive computations at when I import certain modules and would like to know how often the modules will be imported.
This is not a function of Django at all, but of whatever system is being used to serve Django. Usually that'll be wsgi via something like mod_wsgi or a standalone server like gunicorn, but it might be something completely different like FastCGI or even plain CGI.
The point is that all these different systems have their own models that determines process lifetime. In anything other than basic CGI, any individual process will certainly serve several requests before being recycled, but there is absolutely no general guarantee of how many - the process might last several days or weeks, or just a few minutes.
One thing to note though is that you will almost always have several processes running concurrently, and you absolutely cannot count on any particular request being served by the same one as the previous one. That means if you have any user-specific data you want to persist between requests, you need to store it somewhere like the session.

How to handle local long-living objects in WSGI env

INTRO
I've recently switched to Python, after about 10 years of PHP development and habits.
Eg. in Symfony2, every request to server (Apache for instance) has to load eg. container class and instantiate it, to construct the "rest" of the objects.
As far as I understand (I hope) Python's WSGI env, an app is created once, and until that app closes, every request just calls methods/functions.
This means that I can have eg. one instance of some class, that can be accessed every time, request is dispatched, without having to instantiate it in every request. Am I right?
QUESTION
I want to have one instance of class since the call to __init__ is very expensive (in both computing and resources lockup). In PHP instantiating this in every request degrades performance, am I right that with Python's WSGI I can instantiate this once, on app startup, and use through requests? If so, how do I achieve this?
WSGI is merely a standardized interface that makes it possible to build the various components of a web-server architecture so that they can talk to each other.
Pyramid is a framework whose components are glued with each other through WSGI.
Pyramid, like other WSGI frameworks, makes it possible to choose the actual server part of the stack, like gunicorn, Apache, or others. That choice is for you to make, and there lies the ultimate answer to your question.
What you need to know is whether your server is multi-threaded or multi-process. In the latter case, it's not enough to check whether a global variable has been instantiated in order to initialize costly resources, because subsequent requests might end up in separate processes, that don't share state.
If your model is multi-threaded, then you might indeed rely on global state, but be aware of the fact that you are introducing a strong dependency in your code. Maybe a singleton pattern coupled with dependency-injection can help to keep your code cleaner and more open to change.
The best method I found was mentioned (and I missed it earlier) in Pyramid docs:
From Pyramid Docs#Startup
Note that an augmented version of the values passed as **settings to the Configurator constructor will be available in Pyramid view callable code as request.registry.settings. You can create objects you wish to access later from view code, and put them into the dictionary you pass to the configurator as settings. They will then be present in the request.registry.settings dictionary at application runtime.
There are a number of ways to do this in pyramid, depending on what you want to accomplish in the end. It might be useful to look closely at the Pyramid/SQLAlchemy tutorial as an example of how to handle an expensive initialization (database connection and metadata setup) and then pass that into the request-handling engine.
Note that in the referenced link, the important part for your question is the __init__.py file's handling of initialize_sql and the subsequent creation of DBSession.

How do I collect up logs for an App Engine request using Python logging?

Using Google App Engine, Python 2.7, threadsafe:true, webapp2.
I would like to include all logging.XXX() messages in my API responses, so I need an efficient way to collect up all the log messages that occur during the scope of a request. I also want to operate in threadsafe:true, so I need to be careful to get only the right log messages.
Currently, my strategy is to add a logging.Handler at the start of my webapp2 dispatch method, and then remove it at the end. To collect logs only for my thread, I instantiate the logging.Handler with the name of the current thread; the handler will simply throw out log records that are from a different thread. I am using thread name and not thread ID because I was getting some unexpected results on dev_appserver when using the ID.
Questions:
Is it efficient to constantly be adding/removing logging.Handler objects in this fashion? I.e., every request will add, then remove, a Handler. Is this "cheap"?
Is this the best way to get only the logging messages for my request? My big assumption is that each request gets its own thread, and that thread name will actually select the right items.
Am I fundamentally misunderstanding Python logging? Perhaps I should only have a single additional Handler added once at the "module-level" statically, and my dispatch should do something lighter.
Any advice is appreciated. I don't have a good understanding of what Python (and specifically App Engine Python) does under the hood with respect to logging. Obviously, this is eminently possible because the App Engine Log Viewer does exactly the same thing: it displays all the log messages for that request. In fact, if I could piggyback on that somehow, that would be even better. It absolutely needs to be super-cheap though - i.e., an RPC call is not going to cut it.
I can add some code if that will help.
I found lots of goodness here:
from google.appengine.api import logservice
entries = logservice.logs_buffer().parse_logs()

Design pattern for multiple consumers and a single data source

I am designing a web interface to a certain hardware appliance that provides its own custom API. Said web interface can manage multiple appliances at once. The data is retrieved from appliance through polling with the custom API so it'd be preferable to make it asynchronous.
The most obvious thing is to have a poller thread that polls for data, saves into a process wide singleton with semaphores and then the web server threads will retrieve data from said singleton and show it. I'm not a huge fan of singletons or mashed together designs, so I was thinking of maybe separating the poller datasource from the web server, looping it back on the local interface and using something like XML-RPC to consume data.
The application need not be 'enterprisey' or scalable really since it'll at most be accessed by a couple people at a time, but I'd rather make it robust by not mixing two kinds of logic together. There's a current implementation in python using CherryPy and it's the biggest mishmash of terrible design I've ever seen. I feel that if I go with the most obvious design I'll just end up reimplementing the same horrible thing my own way.
If you use Django and celery, you can create a Django project to be the web interface and a celery job to run in the background and poll. In that job, you can import your Django models so it can save the results of the polling very simply.

Categories