Python scripting

Talvez pode ser útil para alguém :).

Este script pega a lista de músicas do mpd, seleciona um playlist aleatório, e coloca no ipod shuffle.


#!/usr/bin/python

import os,random

# ipod mountpoint - must be mounted!
MOUNTPOINT="/mnt/ipod"

def get_files():
    '''Reads the list of mp3 files from mpd database'''
    data = open(".mpd.db").readlines()
    files = []
    for l in data:
        fields = l.strip().split(":",2)
        if len(fields) < 2:
            continue
        if fields[0] == "file":
            files.append(fields[1].strip())
    return files

def get_free_space():
    '''Gets available space from IPOD partition'''
    line = os.popen("df -k %s | awk '{print $4}'" % MOUNTPOINT).readlines()[-1]
    return int(line)

def fullcp(file, target):
    '''copies file and directory structure'''
    os.system('tar cf - "%s" | (cd %s && tar xf -)' % (file, target))

if __name__ == "__main__":
    try:
        os.mkdir("%s/mp3" % MOUNTPOINT)
    except:
        print "Not creating %s/mp3!" % MOUNTPOINT
    files = get_files()
    freespace = get_free_space()
    while 1:
        # pega arquivo aleatorio
        pos = random.randint(0, len(files))
        curfile = files[pos]
        del files[pos]
        # determina o tamanho
        res = os.stat(curfile)
        size = res[6] / 1000
        if freespace - size < 1:
            break
        freespace -= size
        # copia
        print "Copying [%8dK left]: %s" % (freespace, curfile)
        fullcp(curfile, "%s/mp3/" % MOUNTPOINT)

É melhor usar ele junto com Shuffle-DB.

Decorators em python

Por alguns meses fiquei pensando - para que servem os decorators em python? Ultimamente é fácil ver código do tipo:
@algum_metodo
def function(params):
____...

Aí hoje finalmente decidi descobrir como que isso funciona, e para que serve.

Em poucas palavras - realmente, decoratos são bem úteis. Eles não introduzem muitas novidades na linguagem, mas possibilitam evitar duplicação de código, e facilitar a implementação.

Por exemplo, suponhamos que precisamos rastrear todas as chamadas a uma de terminada função. Quais são as alternativas que temos?

  • Mudar a função para ela fazer um print toda vez que ela é executada, e toda vez que ela termina;
  • Fazer um wrapper para essa função;
  • Usar um decorator.

Vamos pensar em uma função bem simples:
def minhafunc(s):
____print "<< %s >> " % s

Como que poderiamos fazer o wrapper para esta função esta função? Por exemplo:
def wrapper(func):
____print "entrando na func!"
____ret = func()
____print "saindo da func!"
____return ret

result = wrapper(minhafunc())
Obviamente, isso funciona.. Mas para funções bem simples.

Um outro jeito seria transformar função automaticamente:
def logger(func):
____def wrapper(param):
________print "entrando na func!"
________ret = func(param)
________print "saindo da func!"
________return ret
____return wrapper

minhafunc = logger(minhafunc)

E agora vem a parte “mágica”. Decorators simplesmente permitem com que você evite a transformação de python em LISP, tirando a necessidade de empacotamento explícito dessas funções. Em outras palavras:

@logger
def minhafunc():
...

faz a mesma coisa que:
minhafunc = logger(minhafunc)

só que logo após a declaração da função.

Só isso :). É claro, que tem várias outras utilidades os decorators - facilitar o uso de threads em PyGTK; facilitar desenvolvimento de código sincronizado, etc.

Sem falar que fica bem mais legível o código:
@synchronized
@logged
def minhafunc():
____....

P.S.: O wordpress, para variar, deixa zoado o código.. Mas logo-logo este site vai migrar para Django. Desde que aprendi a mexer com ele, a minha opinião sobre os frameworks web mudou.. e muito! :)