DAEMONIZANDO EM PYTHON

Uma das coisas que eu achei mais legal desde a primeira vez que gerei um código em PythonBAZAR DO ATALIBA foi a facilidade. E, a outra, foram os diversos métodos existentes para daemonizar um script e/ou programa que geramos.
Para quem não sabe, daemon, no mundo UnixBAZAR DO ATALIBA é o famoso serviço do mundo WindowsBAZAR DO ATALIBA. Ou seja, é um programa que funciona sem a necessidade de um terceiro, tal qual o cron ou o anacron.
Ou seja, ele sempre está em funcionamento e executa funções pré-determinadas em código.

É uma ótima forma de manter funcionando, por exemplo, um robô[bb] para ler o diretório de x em x minutos ou outra coisa qualquer. Tudo bem, dirão alguns, isto eu faço com o Cron, mas as possibilidades de se utilizar um daemon são sem dúvida ilimitadas. É só pensar e você vai ver muitas e muitas mesmo.

O modo que eu encontrei e achei mais fácil é o uso de uma classe, chamada pelo seu criador, por um nome muito criativo, daemon.py :P
No fim, o programa é um framework para criação de daemons na linguagem Python. Ele fornece as seguintes facilidades : 

  • Lê direto da linha de comando
  • Lê um arquivo de configuração ( muito, muito legal isto aqui mesmo )
  • Configura o logging ( função do Python, já toda customizada neste framework )
  • Controle do processo via arquivo pid  

Além de outras funções que não vou citar aqui.

Meu primeiro conselho é baixar  a classe aqui e se familiarizar com a mesma.

Não é dificil utilizá-la e ainda, transformá-la para seus fins, se você tiver um pouco de paciência. Para este post, iremos trabalhar com o exemplo que o autor fornece no próprio arquivo de configuração. 

O exemplo se chama HelloDaemon, e é bem interessante. 

import daemon
import logging
import time

class HelloDaemon(daemon.Daemon):
>>default_conf = '/etc/hellodaemon.conf'
>>section = 'hello'

def run(self):
>>while True:
>>>logging.info('The daemon says hello')
>>>time.sleep(1)

if __name__ == '__main__':
>>HelloDaemon().main()

O código é bem legal. Primeiramente, temos o HelloDaemon que herda sua características da classeBAZAR DO ATALIBA mãe daemon ( sim, o arquivo em questão que baixamos contém esta maravilha ).
Depois, passamos por duas estruturas que mostram o arquivo de configuração. Na primeira, dizemos quem é o arquivo com as configurações ( default_conf ) e depois, dizemos em qual seção do arquivo de configuração iremos mexer.
Seção ? Sim, veja que interessante :

[hello]
uid =
gid =
pidfile = ./hellodaemon.pid
logfile = ./hellodaemon.log
loglevel = info

O arquivo contém na primeira linha, a seção entre colchetes. Ou seja, tudo que vier após aquele colchete é daquela seção. Se houvesse um [hello2], tudo após ele estaria contido na seção hello2.
Como pode ser visto, podemos forçar ele a rodar com um uid e gid específico ( o que é bom para daemons com programas relacionados a sockets[bb] tcp, por exemplo ) e em outras duas linhas, você força a gravação do pid e log ( em locais que você achar melhor ).
Por fim, o loglevel ( que aliás, é meio dispensável, pois você pode forçá-lo no código fonte mesmo ).

Como pode ser visto, o arquivo de configuração é uma peça legal, e é onde iremos trabalhar mais tarde no post.

O restante do código é praticamente auto-explicativo. Ele roda o logging.info, que grava no arquivo de log, o daemon disse alô de um em um segundo. 

Isto abre um leque bem legal de opções, como eu já disse. Mas ao mesmo tempo, desde que comecei a usar a classe havia achado um grande defeito ... como personalizar meu arquivo de configuração.
Nas primeiras versões dos programas com este framework eu literalmente criei variáveis e fiz o diabo a quatro para chegar em soluções que estavam bem na minha cara.

Como pode ser visto, a base deste parser de configuração já é meio que nativo do Python. Assim, faltava achar no código aonde eu poderia modificar aquilo para fazer meu arquivo de configuração, do jeito que eu quisesse. 

E não é que eu achei ? Na função read_basic_config, é só procurar pelo seguinte conjunto de linhas :

self.pidfile = cp.get(self.section, 'pidfile')
self.logfile = cp.get(self.section, 'logfile')
self.loglevel = cp.get(self.section, 'loglevel')

Ou seja, se por exemplo, eu quiser um diretorioleitura como variável, eu adicionaria a linha na classe : 

self.diretorioleitura = cp.get(self.section,'diretorioleitura')

Mas como o programa vai conseguir ler isto ? Simplesmente, modificando o arquivo de configuração para isto aqui : 

[hello]
uid =
gid =
pidfile = ./hellodaemon.pid
logfile = ./hellodaemon.log
diretorioleitura=/var/arquivos
loglevel = info

Com isto eu cheguei num uso da classe bem legal nos últimos tempos. Uma coisa que deve ser ressaltada, é que o uso desta nova configuração no código deve ser feita sempre usando o self.diretorioleitura.

Bom, no fim, foi uma dica de iniciante para iniciantes. Espero ter sido útil e estou aberto a dicas mais legais para daemonizar em Python :-)
Como sou iniciante na linguagem, qualquer coisa que me facilite a vida, mais do que este framework já o fez ... será bem vinda :-)