Inércia Sensorial

2021-01-02

Django PostgreSQL used session on Github Actions test error

Filed under: Python — Tags: , , , — inerte @ 16:26

If you’re using the PostgreSQL service on Github Actions as a backend database for your Django tests, you might encounter the following error on any particular test:

django.db.utils.OperationalError: database "test_name" is being accessed by other users
DETAIL:  There is 1 other session using the database.

And the following at the end of your test run:

RuntimeError: generator didn't stop after throw()

The problem is that Django reuses the database connection, and while locally my tests were passing, on Github Actions even though the all tests were passing, somehow a connection to the database created by the tests was still open, and I was getting the error above.

The solution is simple, set CONN_MAX_AGE to 0 (or conn_max_age if you use dj_database_url) on your DATABASES settings when running on Github Actions.

2008-12-01

Alfabeto em Python

Filed under: Python — Tags: , — inerte @ 17:19

Não precisa digitar na mão:

1
alfabeto = 'abcdefghijklmnopqrstuvwxyz'

Isso imprime as letras minúsculas:

1
print map(chr, range(97, 123))

E isso as maiúsculas:

1
print map(chr, range(65, 91))

Mas você também pode contar com o próprio Python (pilhas incluídas, afinal!):

1
2
from string import ascii_letters
print ascii_letters

E de novo:

1
2
3
import string
print string.ascii_lowercase
print string.ascii_uppercase

2007-07-26

Crivo de Eratóstenes em Python

Filed under: Python — inerte @ 12:56

Estou fazendo os desafios do Projeto Euler e nos dez primeiros já vi três com números primos. Meu primeiro algoritmo ingenuamente testava a primalidade de um número tentando dividí-lo por todos os números menores que ele.

Uma lista com 1.000 números primos dessa maneira gera em pouco menos de um segundo no meu computador. Já 2.000, mais de 9 segundos. E 10.001, como pedido por um dos desafios, eu nem tive paciência de esperar os cálculos acabarem. Minha primeira implementação foi a seguinte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def primo(n):
    for i in xrange(2, n):
        if n % i == 0:
            return False
    return True
 
primo_lista = []
n = 1
while 1:
    if primo(n):
        primo_lista.append(n)
        if len(primo_lista) == 1000:
            break
    n = n + 1

Pocurando por métodos mais velozes achei dois, o Crivo de Eratóstenes e o Crivo de Atkin. O primeiro é mais simples, então decidi implementá-lo. O Crivo de Eratóstones é definido assim:

  1. Escreva uma lista dos números entre 2 e o maior número que você quer testar a primalidade. Vamos chamá-la de lista1;
  2. Escreva o número 2, o primeiro número primo, em outra lista que conterá os números primos encontrados. Vamos chamá-la de lista2;
  3. Remova o 2 e todos os múltiplos dele da lista1;
  4. O primeiro número que sobrar da lista1 é primo. Escreva ele na lista2;
  5. Remova essa número e todos os seus múltiplos da lista1. A remoção pode começar da raiz quadrada do número, já que múltiplos menores foram removidos em passos anteriores;
  6. Repita os passos de 4 a 6 até não restarem mais números na lista1;

A classe a seguir, escrita em Python, retorna uma lista com todos os números primos entre 2 e um número especificado (max_n).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
max_n = 50
 
class CrivoDeEratostenes:
    def __init__(self, max_n):
        self.lista = range(2, max_n + 1)
        self.primo_lista = [2]
        self.crivo()
 
    def crivo(self):
        primo_n = self.lista[0]
        max_n = self.lista[-1] + 1
        self.lista.remove(primo_n)
        for n in self.lista:
            if n % primo_n == 0:
                self.lista.remove(n)
        if len(self.lista) > 0:
            self.primo_lista.append(self.lista[0])
            return self.crivo()
        else:
            return self.primo_lista
 
 
print CrivoDeEratostenes(max_n).primo_lista
 
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Pesquisando sobre Eratóstenes na Internet, descobri que ele foi um animal. O grego viveu dois séculos antes de Cristo e conseguiu calcular com 16% de erro a circunferência da Terra. Leu nos papiros de Biblioteca de Alexandria (aonde foi Diretor) que o sol iluminava o fundo de um poço na cidade de Siena (hoje Assuã) ao meio dia do dia mais longo (o solstício) no verão daquele cidade, em 21 de Junho. Ou seja, a luz fazia um ângulo reto com a Terra.

Mas no dia 21 de Junho, quando era meio dia em Siena, o Sol projetava sombras em Alexandria. Eratóstenes conclui então que a Terra era redonda. O ângulo das sombras deu 7º12′, quase 1/50 dos 360º de uma circunferência, então a distância entre Alexandria e Siena multiplicada por 50 seria a circunferência do planeta.

Mandou um pessoal percorrer essa distância e eles voltaram com 925km. E 50 vezes 925 é 46.250 km, enquanto a Terra tem 40.076 km.

Queria crescer de novo pra ser igual a ele 🙂

2005-10-26

RuntimeError: dictionary changed size during iteration

Filed under: Python — inerte @ 18:34

Em Python, o erro do título desse post acontece quando você percorre um dicionário e ele é mudado durante o laço.

Isso pode acontecer quando fazemos:

1
2
3
4
5
6
7
8
9
>>> dicionario = {'nome': 'Julio', 'sobrenome': 'Nobrega'}
>>> for k, v in dicionario.iteritems():
...     print v
...     del dicionario[k]
...
Nobrega
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
RuntimeError: dictionary changed size during iteration

Se você quer mudar o dicionário durante um laço, use keys():

1
2
3
4
5
6
7
>>> dicionario = {'nome': 'Julio', 'sobrenome': 'Nobrega'}
>>> for k in dicionario.keys():
...     print dicionario[k]
...     del dicionario[k]
...
Nobrega
Julio

Isso só é possível porquê keys() retorna uma lista independente do dicionário.

2005-10-23

Thread em Python

Filed under: Python — inerte @ 23:33

Comecei a fazer uma GUI usando o wxPython para tocar um arquivo de música com o código de ontem. Implementei o botão de seleção do arquivo, que até filtra os arquivos a serem mostrados de acordo com as extensões especificadas. No meu caso, *.mp3 e *.ogg.

Só que selecionado o arquivo, a interface travava. Pesquisando no Google, achei como abrir uma thread usando Python. Basta usar o módulo (surpresa) thread ou o threading. A diferença é que o módulo thread é mais baixo-nível (como em low-level, e não que ele te xingue :)), enquanto o módulo threading abstrai o uso e oferece mais opções.

(more…)

MP3 com Python

Filed under: Python — inerte @ 02:45

Sem bibliotecas adicionais como libmpg123 ou gstreamer ou qualquer outra. Puro Python. Bem, quase, já que o PyMedia é escrito em sua maioria em C, mas depois de instalado você pode usar o import para trazê-lo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pymedia.audio.sound as sound
import pymedia.audio.acodec as acodec
 
def playFile(file_name):
    file_extension = file_name.split('.' )[ -1 ].lower()
    parms = {'id': acodec.getCodecID(file_extension), 'ext': file_extension}
    decoder = acodec.Decoder(parms)
    f = open(file_name, 'rb')
    s = f.read(8192)
    r = decoder.decode(s)
 
    snd = sound.Output(r.sample_rate, r.channels, sound.AFMT_S16_LE)
 
    while len(s) > 0:
        if r:
            snd.play(r.data)
        s = f.read(512)
        r = decoder.decode(s)
 
    import time
    while snd.isPlaying():
        time.sleep(.05)

Para tocar um arquivo:

playFile(“arquivo.mp3”)

O PyMedia entende outros formatos de aúdio, como WAV e OGG. Ele também mostra vídeos com o Pygame mas isso eu ainda não testei não 🙂

2005-10-06

Navegando com Mechanoid

Filed under: Python — inerte @ 18:34

Existe um programa chamado Mechanoid feito em Python, uma colagem dos programas que compõem o Mechanize, só que voltado à execução de determinadas tarefas específicas, como entrar no Sourceforge ou conferir o Yahoo Mail.

Basicamente ele emula um navegador, abrindo páginas, clicando em links, preenchendo formulários. É tão fácil que dói os olhos…

(more…)

2005-09-29

SLOC em Python

Filed under: Python — inerte @ 12:18

Um pequeno script em Python para contar o número de linhas de todos os arquivos em um diretório (e sub-diretórios). Apenas edite a variável diretorio.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os.path
 
diretorio = "/var/www/html/site/"
 
def visit(arg, dirname, names):
    for arquivo in names:
        arquivo_caminho = os.path.join(dirname, arquivo)
 
        if os.path.isfile(arquivo_caminho):
            f = open(arquivo_caminho)
            lines = len(f.readlines())
            arquivos.append(lines)
 
arquivos = []
os.path.walk(diretorio, visit, arquivos)
 
print "%s linhas" % sum(arquivos)

Powered by WordPress