Run Pylons controller as separate app? - python

I have a Pylons app where I would like to move some of the logic to a separate batch process. I've been running it under the main app for testing, but it is going to be doing a lot of work in the database, and I'd like it to be a separate process that will be running in the background constantly. The main pylons app will submit jobs into the database, and the new process will do the work requested in each job.
How can I launch a controller as a stand alone script?
I currently have:
from warehouse2.controllers import importServer
importServer.runServer(60)
and in the controller file, but not part of the controller class:
def runServer(sleep_secs):
try:
imp = ImportserverController()
while(True):
imp.runImport()
sleepFor(sleep_secs)
except Exception, e:
log.info("Unexpected error: %s" % sys.exc_info()[0])
log.info(e)
But starting ImportServer.py on the command line results in:
2008-09-25 12:31:12.687000 Could not locate a bind configured on mapper Mapper|I
mportJob|n_imports, SQL expression or this Session

If you want to load parts of a Pylons app, such as the models from outside Pylons, load the Pylons app in the script first:
from paste.deploy import appconfig
from pylons import config
from YOURPROJ.config.environment import load_environment
conf = appconfig('config:development.ini', relative_to='.')
load_environment(conf.global_conf, conf.local_conf)
That will load the Pylons app, which sets up most of the state so that you can proceed to use the SQLAlchemy models and Session to work with the database.
Note that if your code is using the pylons globals such as request/response/etc then that won't work since they require a request to be in progress to exist.

I'm redacting my response and upvoting the other answer by Ben Bangert, as it's the correct one. I answered and have since learned the correct way (mentioned below). If you really want to, check out the history of this answer to see the wrong (but working) solution I originally proposed.

Related

Django code to execute only in development and production

I need to execute some housekeeping code but only in development or production environment. Unfortunately all management commands execute similar to runserver. Is there any clean way to classify what is the execution environment and run the code selectively.
I saw some solutions like 'runserver' in sys.argv
but it does not work for production. And does not look very clean.
Does django provide anything to classify all these different scenarios code is executing at?
Edit
The real problem is we need to initialise our local cache once the apps are loaded with some data that are frequently accessed. In general I want to fetch DB for some specific information and cache it (currently in memory). The issue is, when it tries to fetch DB, the table may not be created, in fact there may not be migration files created at all. So, when I run makemigrations/migrate, it will run this code which tries to fetch from DB, and throw error saying table does not exist. But if I can't run makemigration/migrate, there will be no table, it is kind of a loop I'm trying to avoid. The part of code will run for all management commands, but I would like to restrict it's execution only to when the app is actually serving requests (that is when the cache is needed) and not for any management commands (including the user defined ones).
```python
from django.apps import AppConfig
from my_app.signals import app_created
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
# Code below should be executed only in actual app execution
# And not in makemigration/migrate etc management commands
app_created.send(sender=MyAppConfig, sent_by="MyApp")
```
Q) Send app created signal for app execution other than executions due to management commands like makemigrations, migrate, etc.
There are so many different ways to do this. But generally when I create a production (or staging, or development) server I set an environment variable. And dynamically decide which settings file to load based on that environment variable.
Imagine something like this in a Django settings file:
import os
ENVIRONMENT = os.environ.get('ENVIRONMENT', 'development')
Then you can use
from django.conf import settings
if settings.ENVIRONMENT == 'production':
# do something only on production
Since, I did not get an convincing answer and I managed to pull off a solution, although not a 100% clean. I thought I would just share solution I ended up with.
import sys
from django.conf import settings
if (settings.DEBUG and 'runserver' in sys.argv) or not settings.DEBUG:
"""your code to run only in development and production"""
The rationale is you run the code if it is not in DEBUG mode no matter what. But if it is in DEBUG mode check if the process execution had runserver in the arguments.

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. file init

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
Exception appeared when I added:
import signals
in init.py file (apps/application/init.py)
from models import Review
in signals.py file (apps/application/signals.py)
I want to send an http request when there is an insert in the model Review.
So I need to import Review model (in the __init.py__ file) to execute the following code:
#receiver (pre_save, sender = Review)
def my_handler (sender, ** kwargs):
....
In the Django's source, this is where the exception is comming from:
def check_apps_ready(self):
"""Raise an exception if all apps haven't been imported yet."""
if not self.apps_ready:
raise AppRegistryNotReady("Apps aren't loaded yet.")
As you can see it make sure every apps are ready (loaded). In general, when it is related to signals there are normally 2 situations when this happen.
Circular imports
Make sure there are none in your project. This can cause the error.
Registering signal before the app is loaded
See this for more information. But, one thing that help me understanding how Django works behind the scene is this statement:
It is important to understand that a Django application is just a set of code that interacts with various parts of the framework. There’s no such thing as an Application object. However, there’s a few places where Django needs to interact with installed applications, mainly for configuration and also for introspection. That’s why the application registry maintains metadata in an AppConfig instance for each installed application.
Hence, what you can do is override one of the AppConfig method called AppConfig.ready() which allow you to perform initialization tasks such as registering signals.
# yourApp/__init__.py
default_app_config = 'yourappname.apps.YourAppConfig'
# yourApp/apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
name = 'yourappname'
def ready(self):
from yourappname import signals
Further information
For the sake of explanation, this is the recommend way of doing since Django 1.7+ which is most likely your case. The logic behind it is that the application registry hold a boolean value ready which is set to True only after the registry is fully populated and all AppConfig.ready() methods are called.

Google App Engine Application Cache

In google app engine i have created my own user API appropriately called user so it doesn't interfere with the google app engine API users. Like most multiuser websites, two "versions" of the site are available to the user depending on whether or not they are logged in. Thus is created a file called router.py with the following code
import webapp2
from lib import user
import guest
import authorized
if user.isLoggedIn():
app = webapp2.WSGIApplication(authorized.WSGIHandler,debug=True)
else:
app = webapp2.WSGIApplication(guest.WSGIHandler,debug=True)
the guest and authorized modules are formated like your conventional application script for example:
import webapp2
import os
class MainPage(webapp2.RequestHandler):
def get(self,_random):
self.response.out.write('authorized: '+_random)
WSGIHandler = [('/(.*)', MainPage)]
Thus the router file easily selects which WSGIApplication url director to use by grabbing the WSGIHandler variable from either the guest or authorized module. However the user must close all tabs for the router to detect a change in the isLoggedIn() function. If you log in it does not recognize that you have done so until every tab is closed. I have two possible reasons for this:
isLoggedIn() uses os.environ['HTTP_COOKIE'] to retrieve cookies and see if a user is logged in, it then checks the cookie data against the database to make sure they are valid cookie. Possibly this could have an error where the cookies on the server's end aren't being refreshed when the page is? Maybe because i'm not getting the cookies from self.request.
Is it possible that in order to conserve frontend hours or something that google app engine caches the scripts from the server with in the server's memcache? i Doubt it but i am at a loss for the reason for this behavior.
Thanks in advance for the help
Edit
Upon more testing i found that as suspected the router.py file responded correctly and directed the user based in logged in when a comment was added to it. This seems to indicate caching.
Edit 2
I have uncovered some more information on the WSHI Application:
The Python runtime environment caches imported modules between requests on a single web server, similar to how a standalone Python application loads a module only once even if the module is imported by multiple files. Since WSGI handlers are modules, they are cached between requests. CGI handler scripts are only cached if they provide a main() routine; otherwise, the CGI handler script is loaded for every request.
I wonder how efficient to refresh the WSGI module somehow. This would undoubtably task the server, but solve my problem. Again, this seems to be a partial solution.
Edit 3
Again, any attempt to randomize a comment in the router.py file is ineffective. The id statement looking for user login is completely overlooked and the WSGIApplication is set to its original state. I'm not yet sure if this is due to the module cache in the webapp2 module or thanks to the module cache on the user API. I suspect the latter.
The problem is not "caching", it is just how WSGI applications work. A WSGI process stays alive for a reasonably long period of time, and serves multiple requests during that period. The app is defined when that process is started up, and does not change until the process is renewed. You should not try to do anything dynamic or request-dependent at that point.
replace router.py with:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from lib import user
import guest
import authorized
def main():
if user.isLoggedIn():
run_wsgi_app(authorized.application)
else:
run_wsgi_app(guest.application)
if __name__ == "__main__":
main()
downgrading to the old webapp allows you to change dynamically the wsgi application. it's tested and works perfectly! The CGI adaptor run_wsgi_app allows for the webapp to change it's directory list without caching.

How to call methods of Model Class in Interactive Console locally?

I have been searching this since yesterday and still nothing. From all that researching this is my understanding so far.
You can access your datastore remotely with remote_api_shell.py
Make sure your path is set correctly in your Environment variable.
And according to my understanding the remote datastore that they were talking about is the datastore in appspot.com and not the local one. I don't want to deploy my app right now and hence I want to just work locally, for now atleast.
I created a model named Usersdb in my app. As someone coming from PHP, MYSQL background I thought GQL would have console environment for us to test the queries. But after some googling I found out that you can manipulate local datastore from the interactive console that's in
http://localhost:8081/_ah/admin/interactive
From the post Google App Engine GQL query on localhost I got the idea of performing GqlQuery in the interactive console while in localhost which goes something like this:-
from google.appengine.ext import db
q = db.GqlQuery("SELECT * FROM Userdb where username = 'random_user'")
print q.get().username
But what I really wanted to do was perform method calls like get_by_id() and get_by_key_name() and such in my interactive console without having to test on my app. Like:-
print Userdb.get_by_id(12)
How can I get those running? Do I have to import my python file to the interactive console? I tried doing that too but it crashed app engine. I'm just starting out on app engine. Forgive me if this is a completely stupid question.
You should import the model class that you wrote into your session in the interactive console. For example, if you have a file named model.py in your application, which contains your Userdb class you could write the following in the interactive console:
import model
print model.Userdb.get_by_id(12)

WebApp needs to do something first time only, where to put that logic? Flask or django

The web app I am working on needs to perform a first-time setup or initialization,
where is a good place to put that logic? I dont want to perform the check if a configuration/setup exists on each request to / or before any request as thats kind of not performant.
I was thinking of performing a check if there is a sane configuration when the app starts up, then change the default route of / to a settings/setup page, and change it back. But thats like self-changing code a bit.
This is required since the web app needs settings and then to index stuff based on those settings which take a bit of time. So after the settings have been made, I still need to wait a while until the indexing is done. So even after the settings/setup has been made, any requests following, will need to see a "wait indexing" message.
Im using flask, but this is relevant for django as well I think.
EDIT: Im thinking like this now;
When starting up, check the appconfig.py for MY_SETTINGS, if it is not there
add a default from config.py and put a status=firstrun object on the app.config, also
change the / route to setup view function.
The setup view function will then check for the app.config.status object and perform
The setup of settings as necessary after user input, when the settings are okay,
remove app.config.status or change it to "indexing", then I can have a before_request function to check for the app.config.status just to flash a message of it.
Or I could use the flask.g instead of app.config to store the status?
The proper way is creating a CLI script, preferably via Flask-Script if you use Flask (in Django it would be the default manage.py where you can easily add custom commands, too) and defining a function such as init or install:
from flaskext.script import Manager
from ... import app
manager = Manager(app)
#manager.command
def init():
"""Initialize the application"""
# your code here
Then you mention it in your documentation and can easily assume that it has been run when the web application itself is accessed.

Categories

Resources