Certo dia terminei um projeto em Django e após vários testes finalmente foi ao ar. Feito isso, liguei para o cliente e marcamos uma reunião para o dia seguinte. Na reunião, conversa vai, conversa vem, o sistema é exibido, tudo funcionando, cliente feliz, eu feliz, tudo ótimo e maravilhoso. Eis então que o cliente sugere uma pequena alteração: Alterar uma mensagem emitida ao usuário. Tarefa simples, pensei. Vou abrir o arquivo e alterar uma string. Pronto! Nada complicado ou demorado que exija marcar uma nova reunião para apresentar essa mudança. Em casa eu atualizo o arquivo e fica tudo como está. Erro meu ter pensado assim. Após a modificação ter sido feita, o sistema não quis atualizar por nada. Apertei Crtl+F5, limpei o cache do navegador, testei em outros navegadores… e nada. Só podia ser cache no servidor de hospedagem. Então deletei todos os .pyc e mesmo assim não funcionou. A coisa era do mal mesmo.
Bom, expliquei ao cliente o que estava acontecendo e ganhei algum tempo para tentar resolver. Percebi que alterações feitas no código da aplicação não eram atualizadas em tempo real. Em outras palavras, se seu projeto já está no servidor de produção usando o mod_wsgi e você alterar o código de uma view ou model, a atualização não será refletida no exato momento.
Não me aprofundei no assunto mas aparentemente o mod_wsgi provê um sistema de cache que leva horas para verificar se houve alterações no código da aplicação. De fato, essa é uma atitude inteligente, pois uma vez que o projeto está em ambiente de produção, nenhuma alteração deveria ser feita naquele espaço. As alterações deveriam ser feitas no ambiente de desenvolvimento e só depois de passar nos testes seria levada ao ambiente de produção.
Então fui pedir ajuda ao oráculo (google) e, após algum tempo, encontrei um site contendo um script que me ajudou bastante naquele momento.
Crie um arquivo chamado monitor.py e ponha-o no diretório do projeto. Abaixo o conteúdo do arquivo:
import os import sys import time import signal import threading import atexit import Queue _interval = 1.0 _times = {} _files = [] _running = False _queue = Queue.Queue() _lock = threading.Lock() def _restart(path): _queue.put(True) prefix = 'monitor (pid=%d):' % os.getpid() print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path) print >> sys.stderr, '%s Triggering process restart.' % prefix os.kill(os.getpid(), signal.SIGINT) def _modified(path): try: if not os.path.isfile(path): return path in _times mtime = os.stat(path).st_mtime if path not in _times: _times[path] = mtime if mtime != _times[path]: return True except: return True return False def _monitor(): while 1: for module in sys.modules.values(): if not hasattr(module, '__file__'): continue path = getattr(module, '__file__') if not path: continue if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']: path = path[:-1] if _modified(path): return _restart(path) for path in _files: if _modified(path): return _restart(path) try: return _queue.get(timeout=_interval) except: pass _thread = threading.Thread(target=_monitor) _thread.setDaemon(True) def _exiting(): try: _queue.put(True) except: pass _thread.join() atexit.register(_exiting) def track(path): if not path in _files: _files.append(path) def start(interval=1.0): global _interval if interval < _interval: _interval = interval global _running _lock.acquire() if not _running: prefix = 'monitor (pid=%d):' % os.getpid() print >> sys.stderr, '%s Starting change monitor.' % prefix _running = True _thread.start() _lock.release()
Para finalizar a configuração, altere o arquivo de configuração do mod_wsgi de modo a conter as duas últimas linhas do código abaixo:
import os, sys sys.path.append('/home/usuario/www/apps_wsgi') os.environ['DJANGO_SETTINGS_MODULE']='meuprojeto.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() import meuprojeto.monitor meuprojeto.monitor.start(interval=1.0)
Feito isso as alterações no código serão atualizadas no navegador em tempo real.
Lamento não inserir uma referência para o site do qual copiei o script, pois já faz algum tempo e não me lembro mais o nome nem a URL.
Links Relacionados
http://blog.dscpl.com.au/2009/02/source-code-reloading-with-modwsgi-on.html
http://blog.dscpl.com.au/2008/12/using-modwsgi-when-developing-django.html









Posted in
Tags: 
Cara, com mod_wsgi, basta vc criar um arquivo chamado /tmp/restart.txt no seu projeto que o wsgi recarrega o projeto. O lance é que o deploy de coisas Python (independente de framework) não será igual ao uso de PHP,onde basta substituir os arquivos e estará tudo ok.
É isso!
@Walter
Obrigado pela dica!
Olha só eu divulgando informação incorreta… Pra recarregar o projeto, basta dar um touch no .wsgi que faz a interface com o apache! Abraço.
Muito legal, parabéns pela dica.
Conforme a dica do Walter Cruz, parece que você foi meio pelo caminho das pedras. Mas foi algo que funcionou legal.
No final das contas, o conhecimento e a experiência valeu a pena.
Parabéns e obrigado por compartilhar.
Muito boa a dica, ainda estou pensando em tirar o mod_python para usar o mod_wsgi, tenho algumas dúvidas ainda, e ter essas dicas ja nos ajuda se tivermos problemas.
Abraços