image1 image2 image3 image4 image5 image6 image7 image8 image9 image10
Data de criação:
Data de publicado:
Acessos: 2567

Às vezes eu escrevo programas.  Entre esse programas, alguns são daemons.
Que erro maldito!

Além da confusão com demônios, o que são daemons?

Daemons são os programas que rodam em background no sistema, não precisando de um terminal (console) anexado.  E qualquer tipo de programa pode ser um daemon, pra qualquer finalidade.

Em geral daemons seguem as seguintes regras pra se tornarem daemons:

  1. Mudar pro diretório raiz ("/").
  2. Realizar um fork().
  3. Finalizar o processo pai, ficando somente o filho, criado no fork().
  4. Realizar outro fork().
  5. Finalizar o primeiro processo filho, deixando somente o segundo, criado no segundo fork().

O segundo fork() é feito para garantir que o programa, através do segundo processo filho, seja "herdado" pelo processo init do sistema.

Em Python, sempre incluo uma função como essa:

   def Daemonize(self):
      """
      Fork to became a daemon.
      """
      
      if not self.isDaemon:
         try:
            self.run()
         except KeyboardInterrupt:
            sys.exit(0)
         return
      
      os.chdir("/")
      pid = os.fork()
      
      if (pid > 0):
         sys.exit(os.EX_OK)
      else:
         pid = os.fork()
         
         if (pid > 0):
            sys.exit(os.EX_OK)
         else:
            self.run()

Esse é parte de um método, mas poderia ser uma função.  A idéia é usar o getopt() para verificar as opções passadas e entrar no modo de daemon ou não, dependendo da opção passada, que modifica a variável booleana self.isDaemon.

Mas um dos meus programs começou a apresentar o seguinte erro:

helio@goosfraba:~$ connect_TSP.py ccn
IP already setup... skipping root access
Running as daemon
daemonized...
close failed in file object destructor:
IOError: [Errno 10] No child processes
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/apport_python_hook.py", line 66, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
RuntimeError: sys.meta_path must be a list of import hooks

Original exception was:
IOError: [Errno 10] No child processes

Inicialmente achei que era problema no "apport" com meu programa, que usa python-expect.  Mesmo com tal erro, o programa funcionava perfeitamente em background, como daemon.  Várias fontes na Internet, principalmente no Launchpad, o sistema de bug report do Ubuntu, várias pessoas reclamavam de tal erro como sendo problema do apport.

Após muito buscar a origem do problema, não no Ubuntu, mas no python, descobri que alguns file descriptors estavam causando esse erro, por continuarem abertos quando ocorria o fork().  Corrigi da seguinte forma:

   def Daemonize(self):
      """
      Fork to became a daemon.
      """
      
      if not self.isDaemon:
         try:
            self.run()
         except KeyboardInterrupt:
            sys.exit(0)
         return
      
      os.chdir("/")
      pid = os.fork()
      
      if (pid > 0):
         os.close(sys.stdin.fileno())
         os.close(sys.stout.fileno())
         os.close(sys.stderr.fileno())
         sys.exit(os.EX_OK)
      else:
         pid = os.fork()
         
         if (pid > 0):
            os.close(sys.stdin.fileno())
            os.close(sys.stdout.fileno())
            os.close(sys.stderr.fileno())
            sys.exit(os.EX_OK)
         else:
            self.run()

então bastou fechar os descritores de arquivo do STDIN, STDOU e STDERR pra ter certeza que o daemon não sairia com o erro acima.

Happy hacking :-)

Data de criação:
Data de publicado:
Acessos: 2247

Esse enviei 2 apresentações pra Python Brasil.  Uma falando sobre python-twitter (e como faço pra enviar os #FF de sexta-feira) e outra pra falar sobre python em telecomunicações.

Não tenho nada escrito ainda, e vou aguardar a confirmação do trabalho pra começar.  Se der certo, estarei em Brasília no início de outubro :-)

Data de criação:
Data de publicado:
Acessos: 2665

Essa é uma apresentação que fiz na iMasters em abril último, no evento 7Masters sobre python

Não é um curso de python, nem nada próximo disso, mas apenas uma visão de que telecom é na verdade um grande TI, com aplicações que todos nós já conhecemos bem.

7_minutes_python_telecom.swf

Era uma apresentação que deveria levar 7 minutos.  Gastei 20.

 

Data de criação:
Data de publicado:
Acessos: 3280

Fonte: http://www.tiagodoria.ig.com.br/2007/08/28/edelman-prepara-estudo-inedito-sobre-blog-no-brasil/Para quem tem filho adolescente, sabe que as traquitanas tecnológicas tornaram a vida um inferno quando o assunto é estudar.  Controlar o acesso ao computador é fácil, criando regras de bloqueio após certos horários estabelecidos, ou mesmo permissão e filtragem de acessos à sites baseados em URL e squid.

Mas com a chegadas dos dispositivos móveis, como telefones Android e tablets, a coisa não ficou tão fácil.

Restou a opção de bloquear o acesso pelo MAC address nos horários de estudo (que em geral são transformados em horários de soneca durante a tarde ou televisão).

Então fiz um pequeno script em python que bloqueia os MACs já cadastrados, tanto do tablet quanto do smartphone, e libera nos horários em que o computador desktop também está liberado.  Com certeza isso não resolve o problema, mas com adolescentes, em geral, quase nada resolve.

O programa funciona com meu roteador wifi, um WR3G01, que comprei no Dealextreme (mais informações aqui).  É um roteador wireless que se diz compatível com DD-WRT, mas que pra isso exige soldar os contatos da conexão serial na placa e carregar o firmware por tftp (era mais fácil dizer que não suporta então).

 

O programa segue:

#! /usr/bin/python
import re, urllib2
from base64 import encodestring
from sys import argv

MACS = [ "94:63:AA:BB:CC:DD", "74:E1:AA:BB:CC:DD" ]
login = "admin"
password = "admin"
server = "192.168.0.1"
port = 80
URI = "/apply.cgi"

TAG =""
for mac in MACS:
  mac = re.sub(":",'%3A', mac)
  TAG += mac + '%3B'

def Usage():
  print "Use: %s {block|allow}" % argv[0]
  exit(1)


if (len(argv) < 2):
  Usage()
elif (not re.search("allow|block",argv[1])):
  Usage()
  
msg_body = "submit_button=wlan_access&" + \
  "change_action=&" + \
  "action=Apply&" + \
  "AccessControlList0=" + TAG + "&"

if (argv[1] == "allow"):
  msg_body += "AccessPolicy0=0&"
elif (argv[1] == "block"):
  msg_body += "AccessPolicy0=2&"
msg_body += "mac=&mac=&mac=&mac=&mac=&mac=&"
if (argv[1] == "allow"):
  msg_body += "selectMAC=1"
elif (argv[1] == "block"):
  msg_body += " selectMAC=3"

http_pass = encodestring(login + ":" + password)
url = "http://" + server + ":" + str(port) + URI

my_headers = {
  'User-Agent' : 'Python Client/1.0/1.0',
  'Authorization' : 'Basic ' + http_pass,
  'Content-Type' : 'application/x-www-form-urlencoded'
}

req = urllib2.Request(
  url,
  headers = my_headers,
  data = msg_body
)

print "Sending: %s" % argv[1]
resp = urllib2.urlopen(req)
Data de criação:
Data de publicado:
Acessos: 3646

Não é de hoje que me deparo com esses erros de unicode em python.

Em algumas funções que uso, principalmente as que lêem de timeline de redes sociais, tenho problemas com caracteres.  Dessa vez eu estava fazendo um programa que lê a timeline da rede social da empresa, que é baseada num produto lixo da Microsoft, o ShamePoint, digo, SharePoint, que publica a API de mensagens no formato RSS.  A função é pra gerar um gráfico de mensagens a cada 5 minutos para verificar o andamento da rede social (que passou do momento de hype).  Então como o ShamePoint é limitado em suas funções, resolvi fazer um "tracking" de posts através de uma função com um hash MD5 da mensagem postada.  

A idéia não é muito complexa, mas eis que fazendo o hash eu achei um:

helio@shibboleet:pynet$ ./mynet_tag_posts.py
Getting posts
Reading output and rss
Traceback (most recent call last):
  File "./mynet_tag_posts.py", line 106, in 
    main()
  File "./mynet_tag_posts.py", line 103, in main
    RSS = RSS_parser(XML)
  File "./mynet_tag_posts.py", line 60, in RSS_parser
    key = md5sum(rss.summary_detail.value)
  File "./mynet_tag_posts.py", line 19, in md5sum
    m.update(msg)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc5' in position 96: ordinal not in range(128)

E a função de hash MD5, a md5sum(), é super simples:

def md5sum(msg):
  m = hashlib.md5()
  m.update(msg)
  return m.hexdigest()

Só que mensagens com caracteres não ASCII, como em português ou suéco, simplesmente matam o processamento do MD5.

Em outros scripts eu contornei isso fazendo uma análise por caractere e substituindo todo aquele que tivesse valor maior que 128 por seu semelhante não acentuado na tabela ASCII.   Trabalho tosco, mas funcional.

Dessa vez resolvi procurar como corrigir isso.  E pra sempre.  Procurei na documentação do python sobre tratamento de unicode.

E não é que achei a solução do jeito mais simples e pythonista possível?  Basta forçar um atributo de formato de caractere no texto, como texto.encode(formato).  No caso, mudei a função para essa abaixo, usando formato de caracteres "utf-8":

def md5sum(msg):
  m = hashlib.md5()
  msg = msg.encode('utf-8')
  m.update(msg)
  return m.hexdigest()

E o problema foi resolvido.  Sem mais chororo de formatos iso-8859-1 e utf-8.  

2017  helio.loureiro.eng.br   globbersthemes joomla templates