Planeta PythonBrasil

PythonBrasil[10]

July 29, 2015

Eric Hideki

O impacto da síndrome do impostor nos profissionais de TI

A área de tecnologia é uma das que mais crescem no mundo. A todo momento surgem inovações e novidades que mudam completamente nosso cotidiano. E com isso são necessários profissionais especialistas em cada assunto. Mas e quem não é especialista, como ele se sente?

Por incrível que pareça, muitas pessoas podem estar com a síndrome do impostor e não sabem.

Mas o que seria isso? Para exemplificar melhor, deixo dois textos muito bacanas que ilustram bem esse sintoma:

http://exame.abril.com.br/revista-voce-sa/edicoes/189/noticias/voce-ja-se-sentiu-um-impostor

http://www.papodehomem.com.br/esta-se-sentindo-um-impostor-voce-nao-esta-so/

Muitos ouvem falar dos desenvolvedores “Rockstar”, aqueles que se destacam pelas suas atividades comunitárias, seja escrevendo artigos, ou dando palestras mundo afora, onde são considerados referências no assunto. O Diego Eis escreveu a respeito sobre essa ideia – http://tableless.com.br/nao-seja-o-proximo-zeno-rocha/. Mas algo que o Zeno relata em outro texto (https://medium.com/@zenorocha/ser-popular-e-uma-merda-b739836e4407) é algo que algumas pessoas podem não perceber:

Lembre-se sempre:popularidade é diferente de competência. Só porque alguém é referência em determinada área, não quer dizer que essa pessoa é melhor tecnicamente que você. De novo, pode parecer clichê mas a gente esquece disso o tempo todo.

E pelo fato de que há pessoas mais articuladas no mercado, que sempre dão as caras em eventos, não quer dizer que o que dizem seja mais importante do que você tenha a dizer.

Assim como a história do Python, a linguagem não foi feita apenas pelo Guido Van Hossun, foi feita por diversas pessoas que tinham o interesse genuíno de compartilhar e colaborar com algo que achavam interessante.

O vídeo abaixo mostra um pouco sobre a história do Python, onde o Guido encaminhou um e-mail para um grupo de amigos e todas as interações feitas são e-mails trocados e projetos que foram nascendo nesse meio tempo.

Não foque nos resultados, foque no processo!

Para chegar em algum objetivo, independente do que for, é necessário o primeiro passo. E o medo do fracasso, como descrito nos textos, é maior do que sua coragem de começar as coisas.

Com isso, é necessário foco e realmente querer, com isso, deixo novamente dois links muito importantes:

http://mel-meow.com/uma-longa-noite-aprendendo/

Conclusões

Muitos tem medo de compartilhar aquilo que sabem, pois o medo das críticas é enorme. Isso é normal e não tem problema algum com isso, mas saiba que o pouco que sabe pode mudar a vida de outra pessoa. Por isso, não deixe de interagir e compartilhar.

Ninguém nasceu sabendo. É meio clichê isso mas nós sempre esquecemos. Tudo leva tempo, e se a pessoa tem bastante capacidade, tenha certeza que isso levou tempo, e porque não podemos, aos poucos, também alcançar essa mesma capacidade? Até porque, precisamos de apenas 20 horas para aprender algo.

Conhece alguém que já teve a síndrome do impostor ou você já teve? Deixe nos comentários como foi constatar o problema e quais foram as soluções que encontrou nesse tempo.


por Eric Hideki em 29 de July de 2015 às 17:21

July 28, 2015

Filipe Saraiva

LaKademy 2015 – meu sprint do Cantor e outros trabalhos

De 3 à 6 de junho o KDE Brasil voltou à Salvador/Bahia para realizar o KDE Latin America Summit 2015 – ou, usando o nome mais bacana, LaKademy 2015.

Aracele já escreveu sobre como o KDE Brasil teve início. É inevitável não pensar aquilo quando falamos sobre KDE e Bahia ao mesmo tempo. KDE tem colaboradores no Brasil e na América Latina em geral desde muitos e muitos anos atrás (KDHelio está aqui para nos lembrar 😉 ) mas o moderno KDE Brasil, orientado à comunidade, com presença contínua nas principais conferências sobre software livre no Brasil, com diversos desenvolvedores, tradutores, e mais, nasceu na Bahia a partir do trabalho do grupo Live Blue – Sandro e Tomaz. Portanto, viajar à Bahia não é apenas uma jornada ao local de nascimento do Brasil moderno – é também uma viagem ao local de nascimento do moderno KDE Brasil.

Meu principal trabalho no LaKademy 2015 foi terminar o port do Cantor para Qt5/KF5. Eu iniciei essa tarefa no LaKademy anterior, e agora foi o momento de terminá-la. Durante o evento me foquei principalmente na remoção do KDELibs4Support. Durante o sprint abri 5 review requests, um para cada biblioteca removida. Agora estou terminando o mecanismo de carregamento de plugins e o trabalho estará terminado.

Mas esta não foi minha única atividade realizada. Durante o evento tivemos alguns projetores para apresentar palestras e material relacionado com contribuição para software livre. Apresentei o processo de revisão de código para os participantes e como submeter requisições de revisão. Isso foi realmente interessante para os novatos.

“Huumm… vamos compilar esse patch e ver o que acontece.”

Colocar diferentes contribuidores e novatos juntos é um momento interessante para troca de dicas e tirar dúvidas sobre diversos aspectos relacionados com contribuição. É interessante ver as diferentes distribuições Linux utilizadas por cada desenvolvedor, como cada um configura seu ambiente de desenvolvimento, e mais. É também um momento legal para sentar lado a lado com outros desenvolvedores para aprender um pouco mais, ou com os novatos para ensinar algo.

Enquanto trabalhei no port do Cantor, fui auxiliado por Daniela e Alana durante a remoção do KDialog. Outro momento legal foi ver a contribuição do Ícaro, Rodrigo e Fernando, adicionando a funcionalidade para automaticamente aumentar o tamanho das bolas no Kollision – precisamos entregar isso aos usuários!

“O que você acha dessa linha?”

E claro, tivemos um encontro de promo para discutir as atividades do KDE no Brasil para esse ano. Quem quiser ver nossas ações e propostas, basta dar uma olhada no quadro do KDE Brasil no kanboard.

Promo Promo Promo Promo Promo Promo

Agora é o momento de espalhar a mensagem do KDE nos eventos brasileiros de software livre – e esse trabalho já começou semanas atrás durante o FISL.

Finalizando, obrigado Sandro por ter organizado o LaKademy 2015 e por toda sua dedicação ao KDE Brasil. Gostaria de agradecer também a todos que contribuíram com o crowdfunding do LaKademy 2015 e ao KDE e.V. – vocês fizeram o evento acontecer! Obrigado também ao Aleix Pol por revisar minhas contribuições de código! =)

E obrigado Salvador por ser essa cidade maravilhosa e sua culinária espetacular! =D

Somos uma família feliz!

por Filipe Saraiva em 28 de July de 2015 às 15:04

July 27, 2015

Galácia

Capoeira Elements and Movements Translated to English

BRAZILIAN PORTUGUESEENGLISH armadaarmed armada com martelo rodadoarmed with spinning hammer aúaooh (phonetic transliteration) bananeirahandstand bençãoblessing benguelabengala (phonetic transliteration) bento grandebig benedict bento médiomiddle genedict berimbaubaereembaoo (phonetic transliteration) botesnake strike cabeçadaheadbutt cadeirachair cocorinhalittle squatting compassocompasses

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 27 de July de 2015 às 12:29

July 26, 2015

Galácia

Considerações Sobre a Revelação do Eu-Sou a Moisés

Na ocasião em que Moisés vê uma sarça (espécie de planta) em chamas mas sem se consumir, Deus se apresenta a Moisés com a expressão que caracterizaria a si próprio: “Eu sou o Deus de seu pai, o Deus de Abraão, o Deus de Isaque, o Deus de Jacó” (Êxodo 3.6). Em seguida, dá uma missão a Moisés, enfrentar o poderoso faraó do Egito e libertar os israelitas. Moisés, entretanto, manifesta certa

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 26 de July de 2015 às 16:08

Calvinismo ou Arminianismo

Este assunto voltou às paradas de sucesso há uns seis anos no Brasil, provavelmente um reflexo do ressurgimento calvinista nos EUA. Nem um nem outro. A cada dia mais me convenço que ambas doutrinas apresentam falhas à luz das Escrituras.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 26 de July de 2015 às 15:15

Algo interessante que aprendemos sobre Jesus, ele não costumava realizar milagres para os incrédulos, mas para os que já estavam crendo nele.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 26 de July de 2015 às 14:59

Sidnei da Silva

Speech therapy made easier

Correcting speech disorders online is called online speech therapy to correct problems. Speech disorder means having a difficulty in communicating with people verbally. It can happen when there is a difficulty in producing certain sounds in terms of fluency and correctness. The ability to receive and comprehend verbal sounds is known as receptive language, and it is a tool used in speech therapy. Speech is a result of coordination between lips, tongue, jaws and vocal tract.

For a person having the speech disorder, all these problems are accommodated, and the speech and learning process is recreated. Because of the better communication through the internet and the advancements in technology, this method is becoming more common where schools and universities also hire the services of famous speech therapists from all over the world. If you have a child who is unable to speak fluently and feels under-confident, you can hire the services of speech therapists from anywhere in the world. There are many benefits of online speech treatment to correct problems.

Speech-language pathologists from anywhere in the world can be appointed for your child. There is no question of limited accessibility because of the innovation in technology. The therapists are culturally and linguistically versatile and would be available outside your office time if you prefer.

Therapy tools that are available online have been beneficial to people and children with speech issues because they have been created in such a way that positive outcomes can be expected. Due to the availability of an SLP on a more frequent basis, the improvement rate is also high.

Learning to speak fluently and communicate in a better way will not only make kids happy, rather, their parents will also be satisfied. Because children have been exposed to the technology at a rate faster than adults of today, they are more attracted towards the gadgets and devices. They like to learn in an interactive manner so the use of digital technology will prove to be much better than simple methods.

Schools, colleges, and other institutes have been able to cut their cost by the reduction in the budget that they kept aside for SLPs before. With SLPs now available, online, there is no expense in terms of employment, travel expenses and management. Besides, the whole process has become a lot more time saving as the travel time has been reduced.

Because of real-time reporting and feedback, any improvement or complaints in the person having speech difficulty is seen by the therapist. Analysis of the situation and the change in strategy is also thus easier.

There are primarily no set up costs involved in offering SLP services to others. All that is needed is a fast internet connection and the devices to interact with students. Headsets, computers, webcams, etc. are sometimes provided by the firm itself.

SLPs that offer online services are usually recognized for the services that they provide. They are known the world over, and the services are widely accepted in different regions. Because of being certified by international training companies, it becomes very easy for SLPs to deliver services.

por admin em 26 de July de 2015 às 13:30

July 25, 2015

Galácia

Que falta me faz o Espírito Santo. Tanta que nem chego a compreender o quanto dele me falta. Minha súplica ao Senhor é a mesma de Davi: "Não me expulse da sua presença, nem tire de mim o seu Santo Espírito" (Sl 51.11).

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 25 de July de 2015 às 16:32

July 24, 2015

Ricbit

Retrocomputação de Verdade #1

Quando eu falo que gosto de retrocomputação, a maioria das pessoas assume que eu estou falando de TK90X e MSX. Mas para mim esses aí não são retrocomputação, são só computação. Eu usei essas máquinas quando elas eram o que havia de melhor (na minha faixa de preço). Antes delas, porém, teve uma época mágica onde computadores eram grandes, barulhentos e ocupavam salas inteiras!

Sempre que eu estou viajando por aí, aproveito a oportunidade para visitar museus de ciência e conhecer esses grandes retrocomputadores do passado. Mas só ver de perto eu não acho tão legal, o que completa a experiência é entender como eles funcionam! Minha idéia original era falar sobre todos os retrocomputadores que já conheci, mas, como ficaria muito grande, vou começar só com os retrocomputadores mecânicos:

O Mecanismo de Antikhytera, 200-100 AC.

Museu Arqueológico Nacional, Atenas, Grécia


A maior prova da engenhosidade grega, o Mecanismo de Antikhytera é muitas vezes chamado de o primeiro computador. Quer dizer, é um computador analógico não-reprogramável, hoje em dia estaria mais próximo do que a gente chama de calculadora.

E para que ele serve? O Mecanismo tem a função de calcular intervalos de tempo: você gira uma manivela que aciona o ponteiro dos anos, e ele ajusta sozinho os outros ponteiros, que são muitos. Ele calcula o mês, a fase da Lua, a posição dos planetas, os eclipses mais próximos, a data da Olimpíada, a constelação do Zodíaco e assim por diante.

Todos esses cálculos são baseados em engrenagens dentadas. Se você tem uma engrenagem com x dentes ligadas a outra com y dentes, a segunda vai rodar com velocidade angular igual a x/y da original. Então você só precisa saber a razão entre a duração de um mês e um ano para fazer um ponteiro que indica o mês.

Mas os gregos eram realmente espertos, e sabiam que algumas relações você não consegue fazer só com razões. A posição da Lua, por exemplo. Eles sabiam que a Lua anda mais devagar em alguns trechos que em outros (por causa do que hoje conhecemos como segunda Lei de Kepler), e, para simular esse efeito, eles fazem uma das engrenagens não ter o centro fixo, assim ela tem velocidade angular variável com a posição.

E como sabemos tanto sobre ela, dado que só temos pedaços de um exemplar que foi achado em um naufrágio? É que um dos pedaços era o manual!

Olhe as inscrições em grego

Essa é a parte legal de visitar museus e ver essas coisas de perto, dá para prestar atenção nos detalhes!

O Motor de Diferenças, 1822

Museu da História da Computação, Mountain View, USA


O século XIX foi a época do Maxwell, Faraday, Tesla, Edison. A engenharia elétrica estava bombando! Mas, para fazer os circuitos funcionarem, você precisa saber resolver equações diferenciais bem complicadas. Essas contas eram resolvidas com tábuas de logaritmos que simplificavam bastante o processo. Mas quem criava as tábuas de logaritmos?

Em geral elas eram feitas por um batalhão de pessoas que calculavam logaritmos na mão, com seis ou sete dígitos significativos. É um trabalho repetitivo e propenso a erros. Hoje em dia nós sabemos que a melhor maneira de realizar cálculos repetitivos e propenso a erros é um computador, mas o primeiro a ter essa idéia foi o Babbage, em 1822. Nessa época ele conseguiu o financiamento para construir o Motor de Diferenças, que tem uma única finalidade: calcular polinômios. Assim ele teria como aproximar os logaritmos por séries de Taylor equivalentes.

Depois de sugar dinheiro do governo por vinte anos sem entregar nada, o financiamento foi cortado. (O governo percebeu que com aquela dinheirama toda dava para contratar gente o suficiente para calcular os polinômios e conferir as contas). Mas foi uma pena, porque o projeto do Babbage era sólido. Se tivesse sido terminado, nunca mais alguém precisaria fazer esse tipo de conta.

Mas será que o Babbage teria conseguido terminar, se não tivesse perdido o contrato? Em 1985, cientistas resolveram seguir o projeto original e montar um Motor de Diferenças de verdade. Eles descobriram que o projeto tinha pequenos erros, mas os erros eram tão bobos que certamente foram introduzidos de propósito, como forma de proteção contra cópia (a técnica de introduzir erros como proteção contra pirataria foi usada desde a Renascença, quem costumava fazer isso era o Leonardo da Vinci). Corrigindo os erros propositais, o Motor funciona! Atualmente tem duas réplicas em funcionamento, uma em Londres e outra na Califórnia.

Por dentro, o Motor de Diferenças também funciona com engrenagens como a Mecanismo de Antikhytera, mas com uma diferença fundamental. O Mecanismo codificava a informação como um ângulo da engrenagem, se você quisesse mais precisão, precisava aumentar fisicamente o tamanho da engrenagem. O Babbage queria precisões de sete dígitos significativos, aí esse método é inviável. A solução foi abandonar a codificação analógica e usar engrenagens digitais. Cada engrenagem marca um dígito de 0 a 9, e com sete engrenagens em sequência você codifica os sete dígitos desejados.

Duas engrenagens encaixadas implementam adição ou subtração (já que virando uma delas, a outra vira junto). Mas, se são engrenagens digitais, então falta um detalhe importante: o vai-um. Eu gravei o vídeo abaixo mostrando o carry propagando, garanto que é a coisa mais bonita que você vai ver hoje!

Propagação mecânica de carry

A Bomba de Turing, 1940

Bletchley Park, UK




Sobre a história desse computador eu não preciso falar muito, já que ela foi transformada em um filme: O Jogo da Imitação (tem no Netflix). Eles precisaram transformar a história do Turing num romance heterossexual para ficar palatável para as massas, mas tá valendo, pelo menos agora as pessoas sabem quem foi o Turing.

A máquina que ele criou era conhecida entre eles como a Bomba. Ela tinha uma única função: quebrar o código de criptografia da máquina alemã Enigma, então para entender a Bomba você precisa entender o Enigma antes. As primeiras versões do Enigma era assim:

O Enigma

O coração do Enigma são os rotores (as engrenagens à esquerda, na foto). Ao longo do rotor está sequência alfabética misturada. Quando inserida no slot apropriado, o rotor faz uma cifra de permutação, obedecendo uma tabela como essa:


Ou seja, a letra A no original vira Z, a letra B vira P, e assim por diante. Quebrar esse código é fácil, qualquer criança esperta consegue. Mas o Enigma é mais seguro que isso. Ao invés de um único rotor, ele tem três rotores em sequência, e os três são diferentes: a letra A vira Z, depois no rotor seguinte você pega esse Z e vira F, depois no último o F pode virar Q. E, para complicar mais, cada vez que você aperta uma tecla o rotor gira, ou seja, dá um offset de uma letra no primeiro rotor. Quando o primeiro rotor gira por completo, induz o segundo a girar uma posição, e assim por diante.

Bastante complicado né? Mas isso não é seguro o suficiente em um contexto de guerra mundial. A senha desse sistema é a configuração inicial dos rotores. Você pode encaixar os rotores no slot em qualquer ordem (6 combinações), e iniciando em qualquer ângulo inicial (26^3 combinações). Isso dá um total de 105456 senhas possíveis. Ninguém consegue testar todas essas senhas em um dia. Mas, também, ninguém precisa testar sozinho! É só pegar 105456 soldados e mandar cada um testar uma senha diferente. Um deles vai acertar de primeira! (E 105 mil soldados não é muito, é só lembrar que no Maracanã cheio cabem 80 mil pessoas. 105 mil soldados é um Maracanã e meio só).

Por isso os alemães colocaram na frente da máquina uns plugues adicionais, que servem para permutar letras na entrada. Se você liga um plugue da posição A para a R, então a letra A vira R e a letra R vira A. Eles usavam em média uns dez plugues, então o número de senhas sobe de 105 mil para 100 bilhões. Parece uma solução esperta, mas isso, na verdade, foi uma burrice dos alemães! Desse jeito, é garantido que a letra A nunca vai virar A de novo. Então eles aumentaram o número de chaves, mas diminuíram o espaço de busca.

Agora já dá para entender a Bomba de Turing. A Bomba, na verdade, é um emulador de Enigma (o Turing sempre foi fã de emuladores, seu conceito de máquina universal é basicamente um emulador genérico). Ele tem todos os rotores iguais aos do Enigma, e um motor que gira os rotores em todas as posições possíveis, bem rapidamente. Atrás de cada rotor tem um contato elétrico: se você colocar uma palavra codificada de um lado, e uma palavra traduzida do outro, quando os rotores giraram na posição correta, dá o contato e ele avisa que achou a senha. E na prática ele não precisa girar todas as combinações possíveis. Se em alguma rotação tiver uma letra que foi mapeada nela mesma, você pode cortar a árvore de busca, porque essa senha com certeza está errada.

Então tudo que resta para quebrar o Enigma é achar um par de palavras, uma codificada, e sua correspondente não-codificada. Isso é o que hoje em dia chamamos de known-plaintext attack. Parece difícil, mas existiam vários truques para conseguir pares assim.

Um deles era baseado no tamanho da mensagem máxima dos alemães. Quando estourava o limite de tamanho, eles quebravam a mensagem em duas, e a segunda parte começava com "continuando, ...". Então, quando encontravam pacotes de várias mensagens longas, uma seguida da outra, certeza que uma delas começaria com "Fortsetzung".

Outra maneira era colocando minas explosivas no meio do mar. Os aliados colocavam as minas de um jeito fácil de encontrar, e em um lugar conhecido. Aí era só esperar os alemães acharem as minas. Quando eles achavam, transmitiam as coordenadas pelo rádio, então era só colocar as coordenadas da mina no computador, que eventualmente ele iria achar uma mensagem correspondente.

Quem viu o filme do Turing deve lembrar que no final eles jogam tudo numa fogueira. Isso aconteceu mesmo, quase tudo sobre o projeto foi destruído, e o que não foi era classificado como ultra-secreto. Só na década de 70 é que o mundo descobriu a existência das Bombas de Turing, e hoje em dia temos informação suficiente para recriar uma delas, como essa que está exposição no Bletchley Park.

A Bomba de Turing por dentro

Ainda tem mais computadores que eu conheci de perto, mas os outros ficam para a parte 2 :)

por Ricardo Bittencourt (noreply@blogger.com) em 24 de July de 2015 às 19:11

July 23, 2015

Grupy-DF

1º Sprint do Grupy-DF

No dia 11 de julho de 2015, nos reunimos na casa dos pais da Tânia para realizar o Primeiro Sprint do Grupy-DF. Após uma bela dose de café recapitulamos os temas propostos:

  • Contribuir com o site das PyLadies
  • Colocar no ar os sites de evento das PythonBrasil anteriores
  • Ajudar no desenvolvimento das coisas pendentes da PythonBrasil[11]
  • Contribuir com a tradução dos docs do Django

Após esta breve recapitulação entramos em contato com Filipe para ficar a par da organização e acessos aos servidores da PythonBrasil.

Hangout com o Filipe

Paralelo ao hangout com o Filipe, descobrimos que o site do PyLadies está em Ruby, o que nos levou, após muita pesquisa, ao aprendizado de como preparar um ambiente de desenvolvimento para futuras contribuições para o projeto.

Seguindo em frente abrimos uma chamada no Skype com o Rudá na qual, depois de muito suor, aprendizado e compilação manual de versões pré-históricas do python, conseguimos colocar no ar praticamente todos os sites Plone que estavam fora do ar.

Skype com o Rudá

Segue abaixo a lista dos sites funcionando até o momento desta publicação e seus respectivos links provisórios:

Além disso outros assuntos como o nome da conta do youtube e alguns problemas da wiki foram levantados.

Se você curtiu e quer participar do próximo sprint ou evento do Grupy-DF acompanhe nossos canais de comunicação e ajude a fortalecer esta comunidade.

por Humberto Rocha em 23 de July de 2015 às 06:19

July 22, 2015

Grupy-DF

Como Publicar No Blog Do Grupy-Df

Olá pessoal! Recentemente inauguramos o site do Grupy-DF e alguns membros do grupo estão começando a produzir conteúdos. Como eu fui o "maluco" a propor essa plataforma, achei que seria justo escrever um tutorial para aqueles que desconhecem um pouco o Pelican. Então preparem seus cérebros pois vamos aprender deste virtual env até versionamento de código!

O Que é o Pelican

Primeiramente o Pelican é um gerador de site estático multiplataforma (GNU/Linux, Mac OS e Windows), isto é, nosso site não possui nenhum servidor de aplicação (backend) em execução, ele é composto apenas de arquivos HTML, CSS e JavaScript. Mas por que isso é vantajoso? Eu já escrevi sobre isso no meu site, mas em resumo ganhamos em performance, hospedagem, segurança e versionamento. Como este site receberá publicações de várias pessoas, resolvemos usar as Issues do GitHub para controlar os artigos que estão em processo de descrita (foi criada uma tag Artigos para concentrar todos os trabalhos).

Outra vantagem de utilizarmos o site estático tendo o GitHub como "backend" é que as publicações podem ser controladas por meio de Pull Requests. Desta forma não limitamos as publicações apenas a quem tem permissão no repositório e/ou é membro do Grupy-DF. Já se estivéssemos utilizando um CMS... teríamos que criar uma conta pra esse usuário e confiar a ele acesso à nossa infraestrutura.

Obtendo Uma Cópia do Site

Para obter uma cópia do site você vai precisar do Git. Primeiramente acesse o repositório do site e crie um fork. Uma vez criado fork, clone o site em um diretório qualquer do seu desktop:

$ cd ~
$ git clone git@github.com:magnunleno/grupydf.github.io.git
$ cd grupydf.github.io

O repositório é composto de alguns diretórios principais:

grupydf.github.io
│
├── content
│   ├── articles
│   ├── images
│   └── pages
├── .plugins
└── .themes

É tudo muito intuitivo, o diretório content possui todos os conteúdos, como artigos, imagens e páginas, o .plugins contém todos os plugins do Pelican, e o diretório themes possui o tema que utilizamos no site. Mas não se preocupem, vamos nos focar apenas no diretório contents.

Agora temos que preparar o ambiente.

Preparando o Ambiente

Criar o ambiente de uso do Pelican é muito simples, pra isso você vai precisar de:

  • Python 2.7;
  • VirtualEnv;
  • Conexão de internet;
  • Um terminal;
  • Um editor de texto;
  • Um navegador;

Primeiro abra um terminal e crie um virtual environment para o Python 2.7 (note que este passo não é obrigatório, mas é uma boa prática):

$ virtualenv --prompt "(grupy-df)" ~/venv/grupy-df

Eu gosto de armazenar todos os meus virtual envs em um mesmo diretório (neste caso ~/venv), mas você pode colocar em qualquer outro lugar. Uma vez criado este virtual env, ative-o:

$ . ~/venv/grupy-df/bin/activate

Uma vez ativado o virtual env basta instalar todas as dependências, para isso utilize o seguinte comando:

$ pip install -r requirements.txt

Após instaladas todas as dependências faça uma compilação de teste do site com o comando make html. Ao compilar o site é criado um diretório output, com o conteúdo gerado, não se preocupe, este diretório já está no .gitignore e não deverá ser entrar no seu commit. Para visualizar o site localmente rode o comando make serve (sua linha de comando ficará "presa" pois ela está servindo as páginas neste momento) e acesse a URL http://localhost:8000. Note que todos estes comandos devem ser executados na raiz do repositório, onde se encontra o arquivo de "receitas" do make, isto é, o arquivo Makefile. Para sair do "modo servidor" pressione Ctrl+C e a linha de comando retornará ao normal.

Após algum tempo de uso passe a pegar o costume de sempre executar uma cadeia de comandos para evitar que arquivos de compilações prévias interfiram com a minha visualização atual: make clean html serve. Apenas esta linha de comando limpa o conteúdo do diretório output, gera o site novamente, e entra no modo servidor. Novamente, para sair do modo servidor pressione Ctrl+C.

Escrevendo Seus Próprios Artigos

Para escrever seus próprios artigos sugiro olhar alguns de exemplo no diretório contents/articles. Eu pessoalmente prefiro o uso da linguagem de marcação ReStructured Text, mas o Pelican também suporta a linguagem Markdown. Um artigo tem um cabeçalho fixo, conforme abaixo (em ReST):

Como Publicar No Blog Do Grupy-Df
=================================
:date: 2015-07-22 14:57
:author: Magnun Leno
:category: Tutoriais
:tags: tutorial, tecnico, pelican, site
:image: /images/monty-python-knights.jpg

Ou em Markdown:

Title: Como Publicar No Blog Do Grupy-Df
Date: 2015-07-22 14:57
Author: Magnun Leno
Category: Tutoriais
Tags: tutorial, tecnico, pelican, site
Image: /images/monty-python-knights.jpg

Novamente é tudo muito intuitivo, temos o título do artigo (a primeira linha em ReST, o a precedida por Title: em Markdown) seguido da data de publicação (no formato YYYY-MM-DD HH:MM). Logo abaixo temos o nome do autor, categoria e uma lista de tags. Somente a última tag é algo implementado por mim e não é nativo do Pelican.

A Tag :image:: ou Image: (em Markdown) faz referência à imagem de capa do artigo, que também fica no "cabeçalho" do artigo, conforme print screens abaixo:

Article Image Header

Após estas meta-tags, basta escrever o texto de acordo com a linguagem de marcação adotadas: ReStructured Text ou Markdown. Para mais informações a documentação do Pelican é excelente! Uma vez concluído o artigo, emita novamente o comando make clean html serve e acesse a URL http://localhost:8000 e ver como ficou.

Lembre que o CSS deste site ainda não está completamente concluído e algumas coisas ainda precisam ser melhoradas, como por exemplo a exibição de códigos, tabelas e etc.

Enviando Sua Contribuição

Uma vez concluído o artigo, vamos realizar o commit da alteração:

$ git add content/article/meu-artigo.rst
$ git add content/images/minha-imagem-do-artigo.png
$ git commit -m "Adicionado novo artivo 'meu-artigo'"

Com o commit realizado com sucesso, você pode realizar o push pro seu repositório remoto (GitHub):

$ git push origin pelican

Agora basta enviar um Pull Request do do seu repositório e os gestores do site irão aprovar sua contribuição.

por Magnun Leno em 22 de July de 2015 às 17:57

Francisco Souza

Setting up a Django production environment: compiling and configuring nginx

Here is another series of posts: now I’m going to write about setting up a Django production environment using nginx and Green Unicorn in a virtual environment. The subject in this first post is nginx, which is my favorite web server.

This post explains how to install nginx from sources, compiling it (on Linux). You might want to use apt, zif, yum or ports, but I prefer building from sources. So, to build from sources, make sure you have all development dependencies (C headers, including the PCRE library headers, nginx rewrite module uses it). If you want to build nginx with SSL support, keep in mind that you will need the libssl headers too.

Build nginx from source is a straightforward process: all you need to do is download it from the official site and build with some simple options. In our setup, we’re going to install nginx under /opt/nginx, and use it with the nginx system user. So, let’s download and extract the latest stable version (1.0.9) from nginx website:

% curl -O http://nginx.org/download/nginx-1.0.9.tar.gz
% tar -xzf nginx-1.0.9.tar.gz
Once you have extracted it, just configure, compile and install:

% ./configure --prefix=/opt/nginx --user=nginx --group=nginx
% make
% [sudo] make install
As you can see, we provided the /opt/nginx to configure, make sure the /opt directory exists. Also, make sure that there is a user and a group called nginx, if they don’t exist, add them:
% [sudo] adduser --system --no-create-home --disabled-login --disabled-password --group nginx
After that, you can start nginx using the command line below:
% [sudo] /opt/nginx/sbin/nginx

Linode provides an init script that uses start-stop-daemon, you might want to use it.

nginx configuration

nginx comes with a default nginx.conf file, let’s change it to reflect the following configuration requirements:
  • nginx should start workers with the nginx user
  • nginx should have two worker processes
  • the PID should be stored in the /opt/nginx/log/nginx.pid file
  • nginx must have an access log in /opt/nginx/logs/access.log
  • the configuration for the Django project we’re going to develop should be versioned with the entire code, so it must be included in the nginx.conf file (assume that the library project is in the directory /opt/projects).
So here is the nginx.conf for the requirements above:

user nginx;
worker_processes 2;

pid logs/nginx.pid;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log logs/access.log main;

sendfile on;
keepalive_timeout 65;

include /opt/projects/showcase/nginx.conf;
}
Now we just need to write the configuration for our Django project. I’m using an old sample project written while I was working at Giran: the name is lojas giranianas, a nonsense portuguese joke with a famous brazilian store. It’s an unfinished showcase of products, it’s like an e-commerce project, but it can’t sell, so it’s just a product catalog. The code is available at Github. The nginx.conf file for the repository is here:

server {
listen 80;
server_name localhost;

charset utf-8;

location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://localhost:8000;
}

location /static {
root /opt/projects/showcase/;
expires 1d;
}
}
The server listens on port 80, responds for the localhost hostname (read more about the Host header). The location /static directive says that nginx will serve the static files of the project. It also includes an expires directive for caching control. The location / directive makes a proxy_pass, forwarding all requisitions to an upstream server listening on port 8000, this server is the subject of the next post of the series: the Green Unicorn (gunicorn) server.

Not only the HTTP request itself is forwarded to the gunicorn server, but also some headers, that helps to properly deal with the request:
  • X-Real-IP: forwards the remote address to the upstream server, so it can know the real IP of the user. When nginx forwards the request to gunicorn, without this header, all gunicorn will know is that there is a request coming from localhost (or wherever the nginx server is), the remote address is always the IP address of the machine where nginx is running (who actually make the request to gunicorn)
  • Host: the Host header is forwarded so gunicorn can treat different requests for different hosts. Without this header, it will be impossible to Gunicorn to have these constraints
  • X-Forwarded-For: also known as XFF, this header provide more precise information about the real IP who makes the request. Imagine there are 10 proxies between the user machine and your webserver, the XFF header will all these proxies comma separated. In order to not turn a proxy into an anonymizer, it’s a good practice to always forward this header.
So that is it, in the next post we are going to install and run gunicorn. In other posts, we’ll see how to make automated deploys using Fabric, and some tricks on caching (using the proxy_cache directive and integrating Django, nginx and memcached).

See you in next posts.

por Francisco Souza (noreply@blogger.com) em 22 de July de 2015 às 01:38

Using Juju to orchestrate CentOS-based cloud services

Earlier this week I had the opportunity to meet Kyle MacDonald, head of Ubuntu Cloud, during FISL, and he was surprised when we told him we are using Juju with CentOS at Globo.com. Then I decided to write this post explaining how we came up with a patched version of Juju that allows us to have CentOS clouds managed by Juju.

For those who doesn't know Juju, it's a service orchestration tool, focused on devops "development method". It allows you to deploy services on clouds, local machine and even bare metal machines (using Canonical's MAAS).

It's based on charms and very straightforward to use. Here is a very basic set of commands with which you can deploy a Wordpress related to a MySQL service:

% juju bootstrap
% juju deploy mysql
% juju deploy wordpress
% juju add-relation wordpress mysql
% juju expose wordpress
These commands will boostrap the environment, setting up a bootstrap machine which will manage your services; deploy mysql and wordpress instances; add a relation between them; and expose the wordpress port. The voilà, we have a wordpress deployed, and ready to serve our posts. Amazing, huh?

But there is an issue: although you can install the juju command line tool in almost any OS (including Mac OS), right now you are able do deploy only Ubuntu-based services (you must use an Ubuntu instance or container).

To change this behavior, and enable Juju to spawn CentOS instances (and containers, if you have a CentOS lxc template), we need to develop and apply some changes to Juju and cloud-init. Juju uses cloud-init to spawn machines with proper dependencies set up, and it's based on modules. All we need to do, is add a module able to install rpm packages using yum.

cloud-init modules are Python modules that starts with cc_ and implement a `handle` function (for example, a module called "yum_packages" would be written to a file called cc_yum_packages.py). So, here is the code for the module yum_packages:

import subprocess
import traceback

from cloudinit import CloudConfig, util

frequency = CloudConfig.per_instance


def yum_install(packages):
cmd = ["yum", "--quiet", "--assumeyes", "install"]
cmd.extend(packages)
subprocess.check_call(cmd)


def handle(_name, cfg, _cloud, log, args):
pkglist = util.get_cfg_option_list_or_str(cfg, "packages", [])

if pkglist:
try:
yum_install(pkglist)
except subprocess.CalledProcessError:
log.warn("Failed to install yum packages: %s" % pkglist)
log.debug(traceback.format_exc())
raise

return True
The module installs all packages listed in cloud-init yaml file. If we want to install `emacs-nox` package, we would write this yaml file and use it as user data in the instance:

#cloud-config
modules:
- yum_packages
packages: [emacs-nox]
cloud-init already works on Fedora, with Python 2.7, but to work on CentOS 6, with Python 2.6, it needs a patch:

--- cloudinit/util.py 2012-05-22 12:18:21.000000000 -0300
+++ cloudinit/util.py 2012-05-31 12:44:24.000000000 -0300
@@ -227,7 +227,7 @@
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
out, err = sp.communicate(input_)
if sp.returncode is not 0:
- raise subprocess.CalledProcessError(sp.returncode, args, (out, err))
+ raise subprocess.CalledProcessError(sp.returncode, args)
return(out, err)
I've packet up this module and this patch in a RPM package that must be pre-installed in the lxc template and AMI images. Now, we need to change Juju in order to make it use the yum_packages module, and include all RPM packages that we need to install when the machine borns.

Is Juju, there is a class that is responsible for building and rendering the YAML file used by cloud-init. We can extend it and change only two methods: _collect_packages, that returns the list of packages that will be installed in the machine after it is spawned; and render that returns the file itself. Here is our CentOSCloudInit class (within the patch):

diff -u juju-0.5-bzr531.orig/juju/providers/common/cloudinit.py juju-0.5-bzr531/juju/providers/common/cloudinit.py
--- juju-0.5-bzr531.orig/juju/providers/common/cloudinit.py 2012-05-31 15:42:17.480769486 -0300
+++ juju-0.5-bzr531/juju/providers/common/cloudinit.py 2012-05-31 15:55:13.342884919 -0300
@@ -324,3 +324,32 @@
"machine-id": self._machine_id,
"juju-provider-type": self._provider_type,
"juju-zookeeper-hosts": self._join_zookeeper_hosts()}
+
+
+class CentOSCloudInit(CloudInit):
+
+ def _collect_packages(self):
+ packages = [
+ "bzr", "byobu", "tmux", "python-setuptools", "python-twisted",
+ "python-txaws", "python-zookeeper", "python-devel", "juju"]
+ if self._zookeeper:
+ packages.extend([
+ "zookeeper", "libzookeeper", "libzookeeper-devel"])
+ return packages
+
+ def render(self):
+ """Get content for a cloud-init file with appropriate specifications.
+
+ :rtype: str
+
+ :raises: :exc:`juju.errors.CloudInitError` if there isn't enough
+ information to create a useful cloud-init.
+ """
+ self._validate()
+ return format_cloud_init(
+ self._ssh_keys,
+ packages=self._collect_packages(),
+ repositories=self._collect_repositories(),
+ scripts=self._collect_scripts(),
+ data=self._collect_machine_data(),
+ modules=["ssh", "yum_packages", "runcmd"])
The other change we need is in the format_cloud_init function, in order to make it recognize the modules parameter that we used above, and tell cloud-init to not run apt-get (update nor upgrade). Here is the patch:

diff -ur juju-0.5-bzr531.orig/juju/providers/common/utils.py juju-0.5-bzr531/juju/providers/common/utils.py
--- juju-0.5-bzr531.orig/juju/providers/common/utils.py 2012-05-31 15:42:17.480769486 -0300
+++ juju-0.5-bzr531/juju/providers/common/utils.py 2012-05-31 15:44:06.605014021 -0300
@@ -85,7 +85,7 @@


def format_cloud_init(
- authorized_keys, packages=(), repositories=None, scripts=None, data=None):
+ authorized_keys, packages=(), repositories=None, scripts=None, data=None, modules=None):
"""Format a user-data cloud-init file.

This will enable package installation, and ssh access, and script
@@ -117,8 +117,8 @@
structure.
"""
cloud_config = {
- "apt-update": True,
- "apt-upgrade": True,
+ "apt-update": False,
+ "apt-upgrade": False,
"ssh_authorized_keys": authorized_keys,
"packages": [],
"output": {"all": "| tee -a /var/log/cloud-init-output.log"}}
@@ -136,6 +136,11 @@
if scripts:
cloud_config["runcmd"] = scripts

+ if modules:
+ cloud_config["modules"] = modules
+
output = safe_dump(cloud_config)
output = "#cloud-config\n%s" % (output)
return output
This patch is also packed up within juju-centos-6 repository, which provides sources for building RPM packages for juju, and also some pre-built RPM packages.

Now just build an AMI image with cloudinit pre-installed, configure your juju environments.yaml file to use this image in the environment and you are ready to deploy cloud services on CentOS machines using Juju!

Some caveats:
  • Juju needs a user called ubuntu to interact with its machines, so you will need to create this user in your CentOS AMI/template.
  • You need to host all RPM packages for juju, cloud-init and following dependencies in some yum repository (I haven't submitted them to any public repository):
  • With this patched Juju, you will have a pure-centos cloud. It does not enable you to have multiple OSes in the same environment.
It's important to notice that we are going to put some effort to make the Go version of juju born supporting multiple OSes, ideally through an interface that makes it extensible to any other OS, not Ubuntu and CentOS only.

por Francisco Souza (noreply@blogger.com) em 22 de July de 2015 às 01:37

Speaking at PythonBrasil[7]

Next weekend I’ll be talking about scaling Django applications at Python Brasil, the brazilian Python conference. It will be my first time at the conference, which is one of the greatest Python conferences in Latin America.

Some international dudes are also attending to the conference: Wesley Chun is going to talk about Python 3 and Google App Engine; Alan Runyan will talk about free and open source software, and Steve Holden will be talking about the issues involved in trying to build a global Python user group.

There is also Maciej Fijalkowski, PyPy core developer, talking about little things PyPy makes possible.

As I pointed before, I’m going to talk about scalability, based in some experiences aquired scaling Django applications at Globo.com, like G1, the greatest news portal in the Latin America.

por Francisco Souza (noreply@blogger.com) em 22 de July de 2015 às 01:37

Go solution for the Dining philosophers problem

I spent part of the sunday solving the Dining Philosophers using Go. The given solution is based in the description for the problem present in The Little Book of Semaphores:

The Dining Philosophers Problem was proposed by Dijkstra in 1965, when dinosaurs ruled the earth. It appears in a number of variations, but the standard features are a table with five plates, five forks (or chopsticks) and a big bowl of spaghetti.

There are some constraints:
  • Only one philosopher can hold a fork at a time
  • It must be impossible for a deadlock to occur
  • It must be impossible for a philosopher to starve waiting for a fork
  • It must be possible for more than one philosopher to eat at the same time
No more talk, here is my solution for the problem:
package main

import (
"fmt"
"sync"
"time"
)

type Fork struct {
sync.Mutex
}

type Table struct {
philosophers chan Philosopher
forks []*Fork
}

func NewTable(forks int) *Table {
t := new(Table)
t.philosophers = make(chan Philosopher, forks - 1)
t.forks = make([]*Fork, forks)
for i := 0; i < forks; i++ {
t.forks[i] = new(Fork)
}
return t
}

func (t *Table) PushPhilosopher(p Philosopher) {
p.table = t
t.philosophers <- data-blogger-escaped-0="" data-blogger-escaped-1="" data-blogger-escaped-2="" data-blogger-escaped-3="" data-blogger-escaped-4="" data-blogger-escaped-:="range" data-blogger-escaped-_="" data-blogger-escaped-able="" data-blogger-escaped-anscombe="" data-blogger-escaped-artin="" data-blogger-escaped-chan="" data-blogger-escaped-e9="" data-blogger-escaped-eat="" data-blogger-escaped-eating...="" data-blogger-escaped-eter="" data-blogger-escaped-f="" data-blogger-escaped-fed.="" data-blogger-escaped-fed="" data-blogger-escaped-fmt.printf="" data-blogger-escaped-for="" data-blogger-escaped-func="" data-blogger-escaped-getforks="" data-blogger-escaped-go="" data-blogger-escaped-heidegger="" data-blogger-escaped-homas="" data-blogger-escaped-index="" data-blogger-escaped-int="" data-blogger-escaped-is="" data-blogger-escaped-leftfork.lock="" data-blogger-escaped-leftfork.unlock="" data-blogger-escaped-leftfork="" data-blogger-escaped-leibniz="" data-blogger-escaped-len="" data-blogger-escaped-lizabeth="" data-blogger-escaped-lombard="" data-blogger-escaped-main="" data-blogger-escaped-make="" data-blogger-escaped-n="" data-blogger-escaped-nagel="" data-blogger-escaped-name="" data-blogger-escaped-ork="" data-blogger-escaped-ottfried="" data-blogger-escaped-p.eat="" data-blogger-escaped-p.fed="" data-blogger-escaped-p.getforks="" data-blogger-escaped-p.name="" data-blogger-escaped-p.putforks="" data-blogger-escaped-p.table.popphilosopher="" data-blogger-escaped-p.table.pushphilosopher="" data-blogger-escaped-p.table="nil" data-blogger-escaped-p.think="" data-blogger-escaped-p="" data-blogger-escaped-philosopher="" data-blogger-escaped-philosopherindex="" data-blogger-escaped-philosophers="" data-blogger-escaped-popphilosopher="" data-blogger-escaped-pre="" data-blogger-escaped-putforks="" data-blogger-escaped-return="" data-blogger-escaped-rightfork.lock="" data-blogger-escaped-rightfork.unlock="" data-blogger-escaped-rightfork="" data-blogger-escaped-s="" data-blogger-escaped-string="" data-blogger-escaped-struct="" data-blogger-escaped-t.forks="" data-blogger-escaped-t="" data-blogger-escaped-table="" data-blogger-escaped-think="" data-blogger-escaped-thinking...="" data-blogger-escaped-time.sleep="" data-blogger-escaped-type="" data-blogger-escaped-was="">
Any feedback is very welcome.

por Francisco Souza (noreply@blogger.com) em 22 de July de 2015 às 01:37

July 21, 2015

Magnun Leno

Hack ‘n’ Cast v0.15 - Sistemas Embarcados - Parte 1

Todo mundo utilizou um sistema embarcado, mesmo que sem perceber. Estes sistemas são responsáveis por toda a a revolução do último século.

Baixe o episódio e leia o shownotes

por Magnun em 21 de July de 2015 às 06:38

July 17, 2015

Grupy-DF

8º TutuPy

E hoje, dia 17 de Julho de 2015, os membros do Grupy-DF mais uma vez se reuniram no Restaurante Marambaia (CLS 311 BL C Loja 19 - Asa Sul). Entre uma conversa e outra, rolou muito tutu, algumas cervejas, distribuição de adesivos e livros adquiridos (ambos) em uma compra coletiva e uma longa discussão sobre os principais pontos do último sprint que realizamos.

Ah, e finalmente bateram uma foto do dito cujo!

Tutu

Segue abaixo a listagem de tópicos discutidos:

  • Repercussão do Sprint;
  • Possibilidade de unificar a base de dados das conferências;
  • Definição de que o Sprint pode agilizar vários pontos da APYB;
  • Como a comunidade pode lidar com novos integrantes;
  • Como funciona a diretoria da ApyBR e a votação;
  • Outros pontos da Python Brasil, diretoria de cada conferência e assuntos das listas;
  • Grupys e PUGs, formas de organização e de trabalhar as comunidades aproveitando as skills de cada um;
  • Logística de transporte e hospedagem pra PythonBrasil[11], incluindo a possibilidade de alugar algum lugar, negociando um pacote fechado para ficar mais barato para a galera do Grupy-DF (e de outros estados);
8º Tutupy

Pra fechar o nosso Mestre Zen (Decko de Brito) nos brindou com a seguinte frase célebre:

Gentileza gera gentileza... e gente leza gera gente leza.

E aí, se arrependeu de não ter ido no 8º TutuPy? Então não perca o próximo! Acompanhe o Grupy-DF nas redes sociais e apareça no próximo! Você ainda tem dúvida de como chegar no TutuPy? Então aí vai um mapa...

por Magnun Leno em 17 de July de 2015 às 22:11

Eric Hideki

O email que mandei para a comunidade do Grupy-SP

highres_439842687

Olá pessoal, tudo bom?

Antes de tudo, gostaria de agradecer a presença dos participantes do nosso encontro de ontem, foi show de bola. E também um agradecimento especial aos nossos palestrantes, o conteúdo apresentado foi de altíssima qualidade.

Com isso, gostaria de pedir seu feedback. Não deixe de comentar, sua opinião é indispensável!

http://www.meetup.com/pt/Grupy-SP/messages/boards/thread/49108985/#128267903

Aqui estão os slides e os contatos dos palestrantes:

https://github.com/grupy-sp/encontros/blob/master/2015-07-7comm.md

E as fotos:

http://www.meetup.com/Grupy-SP/photos/26269408/?_locale=pt

Este é um email muito importante. Ele é importante pois algumas coisas que irei falar podem mudar sua maneira de como olhar o Python e sua comunidade.

Antes de tudo, por que existe eventos de comunidade? O meu amigo Carlos Glória vai exemplificar:

https://www.youtube.com/watch?v=_epbbR4EtYw

Eventos de comunidade podem mudar a vida de uma pessoa. Por isso nos esforçamos para que haja esses encontros.

Algo que foi muito legal é saber que houve grande adesão de novos membros. Sejam muito bem vindos!!

Não gosto de fazer muito jabá do meu blog, mas para os iniciantes que tem interesse em saber um pouco mais sobre Python e sua comunidade, acredito que não há lugar melhor.

https://ericstk.wordpress.com/2015/02/16/guia-para-iniciantes-a-programacao-em-python/

Nesse artigo junto podcasts falando sobre a linguagem, sua história, o que ela faz e outras coisas. Logo após falo de cursos gratuitos, livros e etc. Dê uma lida com calma e depois comente sobre o que achou.

Depois disso, o convido a participar das redes sociais da comunidade e comece a trocar ideias e dúvidas:

https://groups.google.com/forum/#!forum/grupy-sp

https://groups.google.com/forum/#!forum/python-brasil

https://www.facebook.com/pythonbrasil

https://www.facebook.com/grupysp

Twitter: mesmos nomes

Slack: https://grupysp.herokuapp.com/

http://wiki.python.org.br/

Considerações finais:

Se tiver interesse, organize seu próprio encontro de Python, veja mais em: https://github.com/grupy-sp/encontros

Participe da Python Brasil, nosso maior evento nacional de Python. É imperdível! – http://pythonbrasil.github.io/pythonbrasil11-site/

Veja o que falei do evento – https://ericstk.wordpress.com/2014/11/09/python-brasil-10-porto-de-galinhas-recife/

Palestre! Ninguém sabe tudo na vida, então o pouco que você acha que sabe vale muito para outra pessoa. Não deixe de contribuir com suas histórias.

Quer um exemplo para verem que não estou mentindo?

https://parucker.wordpress.com/2015/02/18/ela-quer-respirar-quer-ter-sucesso/

Bônus: https://ericstk.wordpress.com/2014/12/23/como-foi-meu-ano-com-python/

Depois a gente senta em alguma mesa de bar e conto mais sobre essas coisas malucas.

Qualquer dúvida, nossos (Meu e do Diego) estão aí. Mande um email e vamos trocar ideias.

Grande abraço!

 


por Eric Hideki em 17 de July de 2015 às 15:21

July 16, 2015

Galácia

Crônicas da Meia-Noite

Era alta noite quando acordei assustado com voz de gente conversando. Dei um salto da cama e corri pra porta para ver quem estava na minha sala. Mas para meu desespero a porta estava trancada. Tentei abrir seguidas vezes, cheguei a machucar o dedo. Nesse meio tempo minha esposa acordou assustada: “O que foi? O que foi?” Eu não respondi nada, meu coração estava disparado e eu não tinha acordado

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 16 de July de 2015 às 13:40

July 15, 2015

Galácia

Isaías foi literal quando disse: Certamente ele tomou sobre si as nossas enfermidades e sobre si levou as nossas doenças. (53.4a). Pois: (...) foram trazidos a ele muitos endemoninhados, e ele expulsou os espíritos com uma palavra e curou todos os doentes. E assim se cumpriu o que fora dito pelo profeta Isaías: "Ele tomou sobre si as nossas enfermidades e sobre si levou as nossas doenças". (

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 15 de July de 2015 às 11:19

Kodumaro

MoonScript

MoonScript Há muito pouco tempo atrás um amigo meu me sugeriu dar atenção à MoonScript. Admito que eu via a linguagem com preconceito, mesmo assim resolvi dar uma olhada.

Resultado: todos os meus códigos em Lua acabaram convertidos para MoonScript. :-)

A linguagem é extremamente enxuta, limpa e poderosa. Não vou entrar em detalhes, se estiver curioso, leia o guia da linguagem.

Mas também não puxei assunto por nada, vou dar alguns exemplos.

Paradigma Funcional

Para lidar com o paradigma funcional, a sintaxe de MoonScript é bem mais concisa e que a de Lua. Por exemplo, o combinador Y.

Lua é uma linguagem estrita e não suporta o combinador Y em sua forma lazy. Como MoonScript é compilado para código Lua, sofre do mesmo mal. Assim, é preciso usar o combinador Z, que é versão estrita do combinador Y.

O combinador Z é definido como: λf.(λx.xx)(λx.f(λv.xxv)). Isso é facilmente representado em MoonScript:
Z = (f using nil) -> ((x) -> x x) (x) -> f (...) -> (x x) ...

Com isso é possível, por exemplo, implementar facilmente o quick sort:
Z = (f using nil) -> ((x) -> x x) (x) -> f (...) -> (x x) ...

tconcat = (...) -> [e for t in *{...} for e in *t]

Z (qsort using tconcat) ->
(xs) ->
if #xs = 1
xs

else
x, xs = xs[1], [e for e in *xs[2,]]
lesser = [e for e in *xs when e = x]
greater = [e for e in *xs when e > x]
tconcat (qsort lesser), {x}, (qsort greater)

Orientação a Objetos

Em Lua é preciso toda uma ginástica com metatabelas para simular eficientemente orientação a objetos. MoonScript tem suporte a classes na linguagem.

Por exemplo, podemos criar uma pilha (stack) facilmente:
import bind_methods from assert require "moon"

class Stack
list: nil

set: (x) =>
@list =
next: @list
value: x

get: =>
v = nil
{value: v, next: @list} = @list if @list
v

bind_methods Stack!

LuaJIT

Como MoonScript compila para código Lua tradicional, você pode gerar código para virtualmente qualquer plataforma que rode Lua, como LuaJIT e LÖVE.

Por exemplo, você pode usar C-structs e metatipos:
ffi = assert require "ffi"
import sqrt from math

ffi.cdef [[
typedef struct { double x, y; } point_t;
]]

local Point = ffi.metatype "point_t",
__add: (o) => Point @x + o.x, @y + o.y
__len: => @\hypot!
__tostring: => "(#{@x}, #{@y})"
__index:
area: => @x * @y
hypot: => sqrt @x*@x + @y*@y

Point

bash$ luajit
LuaJIT 2.0.3 -- Copyright (C) 2005-2014 Mike Pall. http://luajit.org/
JIT: ON CMOV SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse
> moon = assert(require "moonscript.base")
> Point = (moon.loadfile "point.moon")()
> p = Point(3, 4)
> = tostring(p)
(3, 4)
> = p:area()
12
> = #p
5
>
Bem, acho que já fiz propaganda suficiente da linguagem. ;-)

[]’s

por noreply@blogger.com (ℭacilhας, ℒa ℬatalema) em 15 de July de 2015 às 02:57

July 14, 2015

Alien Retro

Arquitetura/Engenharia de Software na Teoria, na Prática, na Guerra

Aviso: Foco em Python. Links em inglês.

Então. Pensei que podia compartilhar uma coleção excelente de vídeos e blogs de engenharia de grandes empresas (Instagram, PayPal, Dropbox, etc…). Nada demais ou segredo, só um post centralizado com algumas coisas interessantes.

Não tem muitos vídeos sobre uma ferramenta “Tal” ou “Aquela Outra Lá” e sim vídeos em um nível mais conceitual. É o que prefiro assistir. Acredito que se você tem um entendimento profundo sobre um determinado tipo de problema, o resto são só ferramentas. Em outras palavras, é primeiro preciso descobrir  se aquilo é de fato um prego para só então correr atrás do martelo.

Entretanto, os blogs de engenharia comumente entram em um pouco mais de detalhes sobre uma ferramenta ou outra. Mas a parte importante é sempre entender porquê escolheram usar uma coisa e não outra. É engraçado perceber enganos que eles cometeram, coisas que às vezes achamos ser impossíveis nesses lugares cheios de talentos.

A escolha de novas (porém testadas) tecnologias pode cumprir um grande papel. Em tempos tão competitivos, pode ser uma advantagem possuir um certo tipo de know-how em tecnologia cutting edge (não tanto, mas vá lá…).

E bem, achei que alguém poderia fazer bom uso disso. Isso é conhecimento no que acredito ser sua mais pura forma: comunitário. Então continuo a passar em frente.

Para os vídeos, eu criei uma playlist (continuarei a adicionar coisas):

https://www.youtube.com/playlist?list=PLm5JiQ4yORZoml627aVKiNa4SO3g9p0l8

Lista de blogs de engenharia:

http://nerds.airbnb.com/
http://techblog.netflix.com/
https://www.paypal-engineering.com/
http://blog.echen.me/
https://codeascraft.com/
https://blogs.dropbox.com/tech/
http://engineering.tumblr.com/
http://code.flickr.net/
http://engineering.quora.com/
https://blog.twitter.com/
http://engineering.foursquare.com/
http://engineering.heroku.com/
http://highscalability.com/
http://instagram-engineering.tumblr.com/
http://engineering.linkedin.com/blog
http://engineering.pinterest.com/
http://feeds.feedburner.com/soundcloudapiblog
https://corner.squareup.com/
https://github.com/blog
http://engineeringblog.yelp.com/

Três agregadores de blogs de Python:

http://planetpython.org/
http://planet.twistedmatrix.com/
http://wiki.python.org.br/planet/

Um agregador de vídeos de conferências de Python (PyCon, DjangoCon, etc…):

http://pyvideo.org/

Se você não sabe, existem vários livros (muito) bons sobre Python e seus usos:

Dive into Python
Think Python
The Hitchhiker’s Guide to Python
Think Complexity
Think Stats
Guide to Data Mining
Test-Driven Development with Python
Text Processing in Python
BioPython Tutorial and Cookbook
Guide to Python Standard Library
Natural Language Processing with Python
Programming Computer Vision with Python

Não é Python, mas é incrível:

The Architecture of Open Source Applications

Python e Algoritmos:

Problem Solving with Algorithms and Data Structures
Data Structures and Algorithms with Object-Oriented Design Patterns in Python

Use Facebook to Comment on this Post

por Nicholas Amorim em 14 de July de 2015 às 18:11

July 08, 2015

PythonClub

Raspando a Web com Python: Introdução

Todo projeto que deseja raspar dados da web se resume ao seguinte loop:

  1. Fazer uma requisição para uma URL;
  2. Processar a resposta (HTML, XML ou JSON);
  3. Extrair os dados;
  4. Deduzir as próximas URLs a visitar;
  5. Repetir o loop.

A parte mais difícil aqui é processar o HTML. É um processo todo delicado, o HTML é cheio de detalhes para tolerar tags que não fecham, símbolos largados nos lugares errados e por aí vai. Por isso é difícil ter um parser (processador) de HTML nas bibliotecas-padrão de qualquer linguagem, seja Python, Ruby, Javascript ou PHP. Já XML e JSON são formatos muito mais estritos e tem parsers nativos em qualquer linguagem.

Vamos ver como pegar os gastos da Copa do Mundo 2014, expostos em XML. Alguns browsers vão exibir o XML como uma árvore, facilitando a visualização da estrutura -- meu browser favorito, o Firefox, faz isso.

Nesse XML você pode ver um elemento maior, o collection, com muitos elementos copa:empreendimento dentro. Esse prefixo copa: corresponde a um namespace, um recurso do XML para poder misturar elementos de vocabulários distintos. É importante prestar atenção nisso para podermos informar o nosso parser de XML.

Para começar o loop, vamos carregar a URL e popular uma árvore de elementos -- uma abstração do Python para podermos manipular mais facilmente esses dados:

from xml.etree import ElementTree
from urllib.request import urlopen

data_url = "http://www.portaltransparencia.gov.br/copa2014/api/rest/empreendimento"

with urlopen(data_url) as datafile:
    data = ElementTree.parse(datafile)

Repare como carregar uma URL no Python 3 tem uma sintaxe confortável, idêntica à sintaxe de abrir arquivos. Agora pra seguir o loop, vamos extrair o que nos interessa: o gasto (valorTotalPrevisto) de cada empreendimento iniciado ou concluído (cujo andamento não esteja no estado 1, Não iniciado).

spending = [float(element.find('./valorTotalPrevisto').text)
            for element in data.iterfind('.//copa:empreendimento',
                                         namespaces={'copa': data_url[:46]})
            if element.find('./andamento/id').text != '1']

Pegar elementos de um ElementTree é fácil usando o método iterfind (retorna um iterável, pra usar com for) ou findall (retorna uma lista propriamente dita). Já pegar o conteúdo de um elemento exige apenas chamar o atributo .text. Fácil, não?

Isso daria certo se os dados fossem consistentes, mas... outro porém! O XML é estrito -- as tags fecham, os símbolos estão no lugar certo, está tudo certo, mas os dados em si não são consistentes. Nem todo elemento copa:empreendimento tem um elemento valorTotalPrevisto dentro. E agora?

É simples: vamos encapsular o processamento desse valor em um método simples, que retorna zero quando não existe valor total previsto (pra facilitar a soma, depois).

def get_cost(element):
    cost = element.find('./valorTotalPrevisto')
    return 0 if (cost is None) else float(cost.text)

Agora basta chamar o get_cost na nossa compreensão de lista:

spending = [get_cost(element)
            for element in data.iterfind('.//copa:empreendimento',
                                         namespaces={'copa': data_url[:46]})
            if element.find('./andamento/id').text != '1']

E aí podemos finalmente somar todos os valores encontrados e imprimir usando o poderoso método format do Python (estude!).

print('Foram gastos {total:.2f} dinheiros do governo brasileiro'.format(
    total=sum(spending)))

Bônus: Uma versão mais idiomática (PYTHONICA) do código está disponível no meu Gist. Fique à vontade para contribuir, comentar, melhorar, etc :)

Agradecimentos ao Fernando Masanori que começou a brincadeira com esses dados!

por Capi Etheriel em 08 de July de 2015 às 15:40

Grupy-DF

7º TutuPy

Na última sexta-feira, também conhecido como dia 03 de Julho de 2015, a trupe do Grupy-DF se reuniu mais uma vez no Restaurante Marambaia (CLS 311 BL C Loja 19 - Asa Sul). Entre um papo descontraído e outro, rolou muito tutu, algumas cervejas e foram distribuídas camisetas e réguas da PythonBrasil[9]/PloneConf 2013.

7º Tutupy

Claro que não podia faltar o papo técnico! Foram discutidas as diferenças e principais características de CGI, FLASK, Django, Plone, Pyramid, web2py e etc, além de uma comparação de alguns SGBDs (Sistemas Gerenciadores de Banco de Dados) como o mongoDB, ZODB, Postgres, dentre outros. O grupo também se enveredou em uma discussão filosófica sobre intermediadores de pagamentos e equivalentes como o PagSeguro, PayPal, Moip, Iugu...

Foi planejado o adiamento do dojo em prol de um sprint de desenvolvimento que irá ocorre no dia 11 de Julho de 2015, na QI 19, Lago Sul (mais informações com a Tânia). Ficou definido esse sprint se focará nos seguintes pontos:

  • Desenvolver o site da Pyladies;
  • Colocar no ar os sites de eventos antigos da PythonBrasil;
  • Ajudar no desenvolvimento de coisas que estão pendentes da PythonBrasil desse ano;
  • Tradução de documentações do Django.

E aí, se arrependeu de não ter ido no 7º TutuPy? Então não perca o próximo! Acompanhe o Grupy-DF nas redes sociais e apareça no próximo! Você ainda tem dúvida de como chegar no TutuPy? Então aí vai um mapa...

por Magnun Leno em 08 de July de 2015 às 02:51

July 07, 2015

Grupy-DF

Bem vindos ao blog do Grupy-DF!

Olá pessoal! Esse é o primeiro artigo do Blog do Grupy-DF, consequentemente irei usá-lo para dar as boas vindas a todos e para informar como estamos procedendo com o desenvolvimento, manutenção e produção deste site. Quero ressaltar a palavra desenvolvimento, pois este ainda não é um trabalho pronto, é um projeto aberto, colaborativo e atualizado constantemente.

Primeiramente, este site está sendo disponibilizado para vocês através do GitHub Pages logo, todo este site é 100% HTML estático, o que nos garante um bom desempenho, um baixo consumo de recursos e uma boa tranquilidade no quesito segurança. Como vocês já podem imaginar, toda a gerência de permissões e publicações também estão sendo feitaas via GitHub, no repositórios do grupydf.github.io, se utilizando Pull Requests e Forks. A propósito, se você encontrar qualquer erro no site, basta abrir uma Issue no nosso repositório.

Mas é claro que não estamos escrevendo o HTML na mão, para nos auxiliar estamos utilizando o gerador de sites estáticos escrito em Python chamado Pelican (v3.6 mais especificamente). Logo, se você simpatiza com o grupo (não necessariamente precisa pertencer ao Grupy-DF) e quer publicar um artigo aqui, basta escrevê-lo utilizando a linguagem de marcação ReStructured Text ou Markdown e enviar um Pull Request.

Caso esteja curioso com o look 'n' Feel do site, ele foi desenvolvido utilizando o framework CSS Materialize.

por Magnun Leno em 07 de July de 2015 às 19:16

July 06, 2015

Bruno Cezar Rocha

10 rules of open source projects

1. Something incomplete is better than nothing at all

If you have a piece of code and you find some value on it, share it to the community, if this is a code snippet share in the form of a gist, even if this is an incomplete peace of software put it on github. If it lacks documentation, tests and code cleanup shere it anyway! If this is only an idea, put it in a repository README or post in to a blog.

2. Explicit is better than implicit (be honest)

Always put good advices and notes in your project README or in code comments, if the code is incomplete as in #1 lack tests, docs and you are not sure if this is safe please make it explicit to the community it is simpler as putting CAUTION: Use at your own risk or Untested alpha version do not use in prodution notes to the project page.

3. Release it carefully

It follows the same principle as item #2, if you think your software is good and has a good value for others or if you are thinking of some kind of profit from it, do careful releases. what it means?

  • Use versioning, tags, semantic versioning
  • Only upload to the Package Distribution Central if you are sure the code is ready for production!

In case of Python we have PyPI and everyone uses pip install your_awesome_project when something is installed throught pip it is ready for production, there is no sense on using a not ready software installed from package distribution, beta testers will use source code and sometimes people who installs software from pip will trust on it without reading the docs (please read the docs). The main problem is that broken packages on pip will be bad for Python itself, specially beginners will think that this is part of official Python platform. be careful!

4. Follow the patterns

Even if you do not like your community patterns, remember you are not alone and since your project is open sourced it belongs to the community! In python we have a set of good practices and PEP8 rules. You can break some special cases (as you can read in The Zen of Python) but you need to be clear on the justification. It will be very better to help and broader addoption if you follow the patterns.

5. Write tests

Maybe you do not like to follow TDD, no problem, you can write tests after development, maybe you do not care of having 100% of coverage, no problem! But please!! write some tests, only you know which tests are the most important and your community will know what to test and testing is the better way to begin contributing to a software, so write at least one test or your project doesn't get confidence.

6. Do not keep waiting for community help, your project depends only on you!

Sometimes you start a great software, release it to github, advertise it on blog posts and social networlks, talk about that on events and even doing all that stuff your project doesn' t get attraction and you demotivate. If you think your project is good keep on rocking it! Do not expect community help, the project depends only on you, and help and addoption will come naturally as it grows and shows its value. It can take some long time to get it.

7. Write the F** Docs!

You do not have to use some difficult documentation platform, neither write in specific weird markup language (a.k.a RST), you can use any writing platform you want (please don't use a word documment). Even more the community is addopting markdown as it default for docummentation, markdown is easy and there is a lot of nice tools as MkDocs. But you dont need it, you can just create a docs folder and fill it with a bunch of .md files, or you can use the built-in github wiki! Even if incomplete, write some docs, not everyone likes to use source code as reference.

8. Write an awesome documentation!

I know it is repeated, but it is important, maybe it is more important than the software itself, because without good docs your software will not be used and you will not get help!

Try to write an awesome documentation, follow good examples, even if your documentation is only a single README file you can do an fucking awesome README file!

9. Tutorials, videos, blog posts

Well, documentation rises again, but now in form of content drops, you have to show users and developers how your software works and what is the value of it, you can give tips on twitter, record screencasts, blog posts, a nice tutorial and advertise show cases. Just do it!

10. Community matters

Build the community, it can be done with simple actions, invite your friends to a sprint, give talks on events, create a nice logo and maybe a cute and funny mascot to print in stickers and stamps and give it to your friends. Help other projects, you can help to fix some bug in a library you are using and then advertise that you are using that library in your own project, so you will start building connections (it can grows to a whole ecosystem).

Let anyone helps! Maybe the most difficult tasks is your priority, but beginners will always try to find easy to solve tasks, so create some simple issues, sometimes adjusting a .css file or fix formatting in docummentation, or get your code PEP8 compliant, or putting badges on your github page is something you can let community to do, it will help your project to gain some angagement, Focus on difficult tasks and create issues for the easy ones, it is a good entry point for contributors!

If you are looking for a great project to contribute give Quokka CMS a try! :)

por Bruno Rocha em 06 de July de 2015 às 19:16

July 05, 2015

Bruno Cezar Rocha

Dealing with linked containers dependency in docker-compose

In docker-compose a common problem is starting services and daemons in containers that depends on services running on linked containers, in example: your app depends on elasticsearch but it is not ready when the app container is started. Solution is to use a wait script.

I knew that docker-compose team is working on adding a WAIT parameter, but while it is not ready we can use a wait script to load our services.

The process is simple, your container will execute a shell script that will try to execute a HEALTH CHECK many times you want before starting the main command. The health check, the command, the sleep and how many loops to try will be defined in environment variables

This is a program that needs to access an elasticsearch server located in 'elastic' host (that will be mapped by compose

access_elastic_search.py

from datetime import datetime 
from elasticsearch import Elasticsearch
es = Elasticsearch('elastic')
es.index(index="my-index", doc_type="test-type", id=42, body={"any": "data", "timestamp": datetime.now()})
print es.get(index="my-index", doc_type="test-type", id=42)

docker-compose.yml

elastic:
    image: elasticsearch
    command: elasticsearch -Des.node.name="YourNodeName"
    ports:
       - "9200:9200"

app:
    image: ubuntu:14.04
    command: wait_to_start
    working_dir: /src
    links:
        - elastic:elastic
    volumes:
        - .:/src
    environment:
        - WAIT_COMMAND=[ $(curl --write-out %{http_code} --silent --output /dev/null http://elastic:9200/_cat/health?h=st) = 200 ]
        - WAIT_START_CMD=python access_elastic_search.py
        - WAIT_SLEEP=2
        - WAIT_LOOPS=10

wait_to_start script

 #!/bin/bash

echo $WAIT_COMMAND
echo $WAIT_START_CMD

is_ready() {
    eval "$WAIT_COMMAND"
}

# wait until is ready
i=0
while ! is_ready; do
    i=`expr $i + 1`
    if [ $i -ge $WAIT_LOOPS ]; then
        echo "$(date) - still not ready, giving up"
        exit 1
    fi
    echo "$(date) - waiting to be ready"
    sleep $WAIT_SLEEP
done

#start the script
exec $WAIT_START_CMD

Now when you start your environment with docker-compose up the app container will start and execute wait_to_start script, which will perform the test defined in WAIT_COMMAND environment variable and will retry until the test succeeds, so it will end executing the program defined in WAIT_START_CMD

Full code on gist: https://gist.github.com/rochacbruno/bdcad83367593fd52005

This code was made with StackOverflow help

por Bruno Rocha em 05 de July de 2015 às 03:12

July 02, 2015

Magnun Leno

ROADSEC 2015 - Recife

O ROADSEC é o maior evento de hacking, segurança e tecnologia do Brasil e conta com palestras, roadhacks, cryptorace e hackaflag, além de patrociados de peso como a Symantec, Aker e LittleBits Electronics. Neste ano ele já passou por cidades como Campo Grande, Brasília, Manaus, Fortaleza, Natal, Aracajú e Salvador, e sua próxima parada é Recife!

O evento ocorrerá na FBV (Faculdade Boa Viagem), Campus Imbiribeira (Rua: Jean émile favre, 422 - Imbiribeira) e as inscrições podem ser feitas no site. Mas…

Entretanto, se o evento não tiver um bom público ele pode não ir pra Recife no ano que vem. Por isso o leitor/ouvinte Tulio Santos nos mandou um cupom que permite você entrar de graça no evento! O código é: RSPE-FR33C0D3

ROADSEC 2015 - Recife

ROADSEC 2015 - Recife é um artigo original de Mind Bending

por Magnun em 02 de July de 2015 às 19:57

Galácia

Nesta crise, o governo não é a solução para os nossos problemas, o governo é o problema. — Ronald Reagan, no discurso de posse dele, janeiro de 1981. (Não que eu concorde inteiramente, mas é algo a se pensar).

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 02 de July de 2015 às 11:43

June 29, 2015

Galácia

Não dê ouvidos aos que disserem a você: repita essas palavras em hebraico, use essas vestimentas dos judeus, adote esses ícones israelenses ou faça esses rituais judaicos. Não são palavras de significado oculto ou ditas em outro idioma que conduzem a Cristo. Nem é o vestir-se como judeu que tornaria alguém mais aceitável a Deus. Tampouco fazer uso de candelabros, taças ou estrelas nos levaria

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 29 de June de 2015 às 13:01

June 27, 2015

Bruno Cezar Rocha

Oportunidade para Programador Python / Data Scientist na Catho

Você gosta de trabalhar com inteligência aplicada?
Não tem medo de aprender novas tecnologias?
Venha trabalhar conosco!
 
A equipe de Inovação da Catho procura por alguém com paixão por conhecimento e espírito inovador.
Nosso foco é produzir novas tecnologias que irão ajudar pessoas a encontrarem as melhores vagas
e empresas a encontrarem os melhores profissionais.
 
Temos dois perfis de vaga:
 

Perfil cientifico, para efetuar analise e desenvolvimento de modelos

e ferramentas voltadas para mineracao de dados e inteligencia artifical;

 
Áreas de conhecimento importantes no nosso dia-a-dia:
  • Machine Learning
  • Sistemas de Recomendação
  • Modelos estatísticos
  • Recuperação de Informação
 

Perfil desenvolvedor, para desenvolver aplicaçoes baseadas em data mining e big data;

 
Desenvolvimento de software:
  • Ambiente: Linux, Git, Github
  • Programação: Python
  • Banco de dados: MongoDB, MySQL, Postgres
  • Web: Flask, Tornado, Javascript, HTML/CSS
Computaçao aplicada:
  • Máquinas de busca: Elasticsearch, Solr
  • Computação em nuvem & alto desempenho: AWS, NewRelic, Otimizaçao de performance
  • Cloud & Big Data
  • Infra: Fabric, NewRelic, MMS
  • Cloud: Amazon
  • Big data: Amazon SWF
 
Requisitos:
 
  • Ser fluente em uma linguagem de programação
  • Ter autonomia para mergulhar em problemas
  • Trabalhar bem em equipe
  • Ter espírito de pesquisador
 
Mais Informações:
 
  • Localização: Tamboré, Barueri/SP
  • Contrato: CLT Full
  • Jornada: Integral/Flexível
  • Benefícios: Plano de Saúde e Dental, VR/VA, Vale transporte,
  • Seguro de vida, Estacionamento, Convênio SESC
  • Remuneração: A combinar
 
Contato:
 
Envie seu resumo profissional para catholabs@catho.com

por Bruno Rocha em 27 de June de 2015 às 20:54

June 19, 2015

Kodumaro

Cython

Nas últimas semanas tenho desenvolvido uma aplicação usando Cython e me surpreendi com o resultado.

Comecei usando o Cython apenas para compilar código Python – o que de fato rendeu o aumento de desempenho prometido –, mas então resolvi ir mais longe pra ver o quanto poderia extrair dessa plataforma: comecei a usar tipagem estática, funções C (cdef) e depois acabei migrando minhas classes para tipos de extensão (cdef classes).

A cada novo passo era perceptível o crescimento do desempenho e da coerência geral do código. Minha única crítica é quanto aos testes: o código fica muito difícil de ser testado, já que não é possível fazer monkey-patch para colocar os mocks.

Segundo a documentação, ao compilar código Python com Cython, você tem um aumento de 35% no desempenho do código. Usando a tipagem estática, o aumento é de 300% e usando funções C e tipos de extensão o aumento é de aproximadamente 15.000%.

Não posso confirmar esses números, pois não fiz medições exatas, mas uma fila do RabbitMQ que enchia com 6, 7 mil mensagens, encheu com 64 mil no mesmo período de tempo (eu estava fazendo apenas carga, sem consumir a fila).

Uma coisa que gostei muito no Cython é o feeling: tem uma pegada bastante parecida com a do Objective C, o que faz sentido.

Vou dar um exemplo da própria documentação do Cython:

Dado o seguinte código Python puro:
def f(x):
return x**2-x

def integrate_f(a, b, N):
s = 0
dx = (b-a)/N
for i in range(N):
s += f(a+i*dx)
return s * dx
Você pode salvar esse código em integrate.pyx e compilá-lo assim:
bash$ cythonize -ib integrate.pyx
Isso irá gerar o código equivalente em C (integrate.c) e compilá-lo na biblioteca integrate.so, que pode ser diretamente importada em Python:
bash$ python
>>> from integrate import integrate_f
>>>
Se você tiver o IPython, pode usar o Cython no prompt:
bash$ ipython
Python 2.7.9 (default, Jan 7 2015, 11:49:12)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> %load_ext Cython
>>> %%cython
from integrate cimport integrate_f
De qualquer forma, só usando a biblioteca compilada em vez do código Python importado, Cython já promete um aumento de 35% de performance – o que não me frustrou.

Além disso, podemos adicionar tipagem ao código: Cython é um superset em Python, ou seja, é uma linguagem em si e um código Python é também código válido Cython.
def f(double x):
return x**2-x

def integrate_f(double a, double b, int N):
cdef:
int i
double s, dx
s = 0
dx = (b-a)/N
for i in range(N):
s += f(a+i*dx)
return s * dx
Segundo a documentação, isso garante um desempenho 4 vezes superior ao de Python.

No entanto ainda é possível otimizar mais ainda o código! Cython tem uma sintaxe específica que gera código C diretamente, cdef:
cdef double f(double x) except? -2:
return x**2-x

def integrate_f(double a, double b, int N):
cdef:
int i
double s, dx
s = 0
dx = (b-a)/N
for i in range(N):
s += f(a+i*dx)
return s * dx
O desempenho dessa função f em C promete ser 150 vezes melhor do que a mesma função em Python puro.

O except? -2 na função é usado para passar exceções para o código C. Em um outro momento posso entrar em mais detalhes.

Tipo de extensão

Tipos de extensão são equivalentes às classes de Python, porém mais restritos e muito mais eficientes.

Por exemplo, da a seguinte classe:
class Consumer(object):

def __init__(self, backend):
self.backend = backend

def run(self, handler):
resp = self.backend.get()
return handler.handle(resp)
Considerando que as instâncias só serão executadas em Cython, o código equivalente estaria em dois arquivos, o primeiro consumer.pxd:
from backends.base cimport Backend
from handlers.base cimport Handler

cdef class Consumer:

cdef:
Backend backend
int run(self, Handler handler) except? -1
Esse código .pxd equivale ao cabeçalho .h de C. Agora, o arquivo de implementação deve ser chamado consumer.pyx:
from backends.base cimport Backend
from handlers.base cimport Handler

cdef class Consumer:

def __cinit__(self, Backend backend):
self.backend = backend

cdef int run(self, Handler handler) except? -1:
cdef dict resp = self.backend.get()
return handler.handle(resp)
Esse código promete ser muito mais eficiente que sua versão em Python, infelizmente métodos declarados como cdef são acessíveis apenas em C (e em Cython). Para que o método seja acessível em Python, ele deve ser criado como um método Python comum (def) ou pode ser usado cpdef.

O comando cpdef (C/Python def) cria a função C (como cdef) e um wrapper em Python para torná-la acessível. Se o módulo for importando com cimport, será usada a função C original; se for importado com o clássico import, será usado o wrapper.

Conclusão

Até agora não tive motivos para me arrepender de usar Cython, recomendo.

[]’s
ℭacilhας, La Batalema

por noreply@blogger.com (ℭacilhας, ℒa ℬatalema) em 19 de June de 2015 às 16:10

June 16, 2015

Thiago Avelino

Eu nunca mais vou empreender

Empreender é viver novas experiências todos os dias

Para quem não me conhece eu tive uma startup durante um tempo e ela foi comprada por uma empresa de fora do Brasil. Logo após a venda da startup eu prometi para mim mesmo que nunca mais empreenderia, sim isso foi um comentário que fiz em um dos meus momentos de reflexão e nunca comentei com ninguém até então.

Porque eu prometi isso para mim?

Empreender não é um processo simples, não existe mar de rosas no caminho do empreendedor e como tudo temos altas e baixas (e por sinal mais baixa do que alta). Eu fui sócio do Christiano Anderson durante um tempo e ele foi e ainda é uma inspiração para mim como desenvolvedor e empreendedor, passava horas e horas tomando cerveja com ele entendendo algumas tomadas de decisão na vida dele e isso me fez ter ele como uma referência (e por sinal uma ótima referência). Voltando ao motivo, antes de vender à startup meu filho tinha nascido e empreender com uma criança recém-nascida foi um processo complicado, esposa precisando de atenção (mais do que o comum) e eu tendo que desenvolver solução para melhor atender os clientes, nessa fase logicamente que foi uma fase de baixa (poucos clientes). Como em muitos casos não tínhamos planejado ter filho, mas que venha com saúde.

Á volta para o mercado de trabalho!

Quando voltei para o mercado de trabalho queria ter estabilidade dentro da empresa e com isso aceitei algumas condições de trabalho não muito favorável (mas condições que muitas pessoas que mora em São Paulo – Capital aceita), eu andava media de 42 km para ate o escritório, sim 84 km por dia dentro de uma máquina de 4 rodas (chamada carro) e fazia papel de gerente de projeto (para quem não sabe eu tinha certificado PMP, que venceu em 2014 e não tenho a mínima vontade de renovar). Meu dia a dia era mandar e-mail e dar prazo para projeto, sei que isso na área de tecnologia não é muito fácil (mas é o que tem para hoje). Chegava em casa extremamente cansado por ter trabalhado o dia todo e consequentemente ter participado do trânsito de uma megalópole (em São Paulo, você não pega transito e sim participa, é muitas horas para falar que pegou transito). Logicamente que não fiquei muito tempo nessa vida e resolvi procurar outra oportunidade e fui trabalhar home office (remoto) como desenvolvedor. Agora sim cheguei onde eu quero, trabalhando de casa, vendo meu filho crescer, ate ir para PythonBrasil[10] e passar algumas horas conversando com o Henrique Basto que me fez algumas perguntas que o Renzo e Bruno Rocha tinha feito a 1 ano atrás e eu ainda não sabia responder.

A volta para os empreendedorismos…

“Porque você trabalha para os outros ainda? Você não consegue viver da renda do samba (site de conteúdo adulto, link para +18)?”

Isso fez eu refletir alguns meses e juntar com uma grande vontade que tinha que era sair da Capital e ir morar no interior. Após convence a esposa foi hora de procurar cidade e casa. Lembrei do Cadu que tinha comentado e convidado de eu de vir morar no Vale do Paraíba quando estava trabalhando remoto. Escolhi uma cidade tranquila próximo de SJC para morar com minha família (Caçapava, e viva a Taiada).

Sim vamos viver de samba, após 1 mês morando no Vale e empreendendo, o samba me fez sambar, a empresa que mantinha o fluxo do caixa do samba resolveu aplicar algumas regras, que fez o samba não consegui sacar o dinheiro que estava rendendo, sem eu pensar estava novamente empreendendo.

Após isso acontecer, comecei pensar que tinha feito a pior escolha da minha vida em ter saído da Capital e vindo morar no Vale, eu não tinha ligado o nome Vale do Paraíba com Vale do Silício. Sim o Vale do Paraíba respira empreendedorismo, principalmente dentro do Parque Tecnológico de SJC. Onde fez eu retomar meu espírito empreendedor e começa novamente empreender.

Hoje posso afirma que empreender é viver novas experiências todos os dias e tirar energia de onde você meno espera.

Devo muito (mas muito) ao Cadu e Nando por algumas horas de bate papo sobre como eles fazem as coisas acontecer dentro da ZNC e experiência de vida empreendedora.

por avelino em 16 de June de 2015 às 15:15

June 14, 2015

PythonClub

Instalando o PyCharm no Ubuntu (e irmãos)

O objetivo aqui é instalar o PyCharm no Ubuntu e distribuições "irmãs" (como o Mint); estou instalando a versão Community Edition, que acredito que é a que muita gente que começa com essa poderosa IDE vai instalar pra dar os primeiros passos, experimentar.

(aliás, bom avisar antes de começar: fiz o guia baseado no Ubuntu 14.04 e no Linux Mint 17.1; mas já fiz o mesmo procedimento em versões anteriores tanto do PyCharm quanto do Ubuntu, e com a versão "Professional" do PyCharm, e funcionou bem.)

Parte 1 - instalar o Java

As aplicações da JetBrains não são exatamente compatíveis com a versão do Java que vem por padrão no Ubuntu. Por isso, precisamos atualizar.

Abra o terminal e execute os comandos abaixo:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
sudo apt-get install oracle-java8-installer -y
sudo apt-get install oracle-java8-set-default -y

Após os comandos acima, veja se a instalação está correta, executando no console:

java -version

a saída esperada é algo como:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

Parte 2 - pip e virtualenv

O PyCharm usa o pip para baixar módulos/bibliotecas/extensões (como quiser chamar) do python, e o virtualenv para criar os queridos ambientes virtuais que mantém a sanidade dos programadores python. Então, para tirar proveito dessas funcionalidades, é bom garantir que estejam instalados também.

Para isto, abra o console e:

cd ~/Downloads
wget -c https://bootstrap.pypa.io/get-pip.py
sudo -H python2 get-pip.py
sudo -H python3 get-pip.py
sudo -H pip2 install virtualenv

Parte 3 - copiar o PyCharm

  • clique no link ao lado para ir à página de Download do PyCharm
  • clique em "Download Community"
  • grave o arquivo no diretório que quiser

Parte 4 - instalar o PyCharm

Com os pré-requisitos prontos e instalados, vamos ao prato principal:

sudo tar -C /opt/ -xzf <diretorio_onde_gravou_o_download>/pycharm-community-4.5.1.tar.gz
  • Abra o navegador de arquivos e vá ao diretório /opt/pycharm-community-4.5.1
  • Entre no diretório 'bin' e, com dois cliques sobre, execute o script 'pycharm.sh'
  • Se aparecer uma janela perguntando como rodar o programa, clique no último botão ('Executar' ou 'Run')
  • Dê "OK" na janela que abrir
  • E na próxima janela, deixe todas as últimas opções selecionadas. Ao clicar em 'OK' o PyCharm vai pedir a senha de 'root' para criar as entradas no menu.

Tela de configuração final

Pronto, é isso. O software está instalado, e pronto para uso.

por Erick Müller em 14 de June de 2015 às 15:58

June 10, 2015

Bruno Cezar Rocha

The Developers Conference 2015 Sp Trilha Python

Olá,
Eu, o Diego Garcia e o @gutomaia estamos organizando a trilha de‪#‎python‬ do The Developer's Conference SP 2015, Um dos maiores eventos de tecnologia do Brasil.

Gostariamos de sua ajuda para escolher os temas a serem abordados, preencha o formulário para sugerir temas ou propor uma palestra:

http://goo.gl/forms/P2HgcnBFsA

Além das palestras que já podem ser submetidas através do site oficial do evento, também estamos agilizando uma maneira de toda a comunidade participante colaborar com o evento sugerindo os temas e apresentando palestras relâmpago no dia do evento.

Palestras relâmpago são famosas nos eventos de Python e não são apenas pequenas palestras de 5 minutos, é muito mais que isso, não seria simplesmente ir lá na frente e falar sobre algum assunto.

Uma boa palestra relâmpago deve atingir seu objetivo que é o de em apenas 5 minutos mostrar uma idéia completa! de forma que a platéia capte com clareza a natureza da proposta, o valor que ela oferece e o caminho para o próximo passo no assunto proposto.

É um desafio interessante e bastante motivador principalmente para aqueles que estão começando a participar como palestrante e que desejam dar o primeito passo. Gostariamos de convidar toda a comunidade Python que estará presente no evento a propor, preparar e apresentar uma dessas! topa?

Loading...

por Bruno Rocha em 10 de June de 2015 às 18:52

June 08, 2015

Galácia

Por que as leis da física são da maneira como são? O que determina o acaso?

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 08 de June de 2015 às 13:12

June 07, 2015

PythonClub

A armadilha dos argumentos com valores padrão

Algo muito comum em várias linguagens de programação é a possibilidade de definir valores default (valores padrão) para argumentos de funções e métodos, tornando a utilização desses opcional. Isso é ótimo, principalmente para manter retrocompatibilidade, porém, o python possui uma pequena armadilha que caso passe despercebida, pode causar sérios problemas, muitas vezes difíceis de serem detectados. Essa armadilha ocorre quando usamos valores de tipos mutáveis como valor default de argumentos.

O que são tipos mutáveis e imutáveis?

Segundo a documentação oficial do python, o valor de alguns objetos pode mudar, esses objetos que podem ter seu valor alterado após serem criados são chamados de mutáveis, enquanto que os objetos que não podem ter seus valores alterados após serem criados são chamados de imutáveis (simples assim).

  • Tipos mutáveis:

Listas, Dicionários e tipos definidos pelo usuário.

  • Tipos imutáveis:

Numeros, Strings e Tuplas.

Apesar de serem imutáveis, a utilização de um valor mutável (uma lista por exemplo) dentro de uma tupla, pode causar o efeito tuplas mutáveis, onde visualmente o valor da tupla é alterado, mas por trás dos panos o valor da tupla não muda, o que muda é o valor do objeto pelo qual a tupla está se referenciando.

A armadilha

Como disse no começo desse blogpost, é muito comum a utilização de valores default em agurmentos de funções e métodos, por essa razão, nos sentimos seguros em fazer algo desse tipo:

def my_function(my_list=[]):
    my_list.append(1)
    print(my_list)

Porém, levando esse exemplo em consideração, o que irá acontecer se invocarmos essa função 3 vezes?

>>> my_function()
[1]
>>> my_function()
[1, 1]
>>> my_function()
[1, 1, 1]

Sim, o valor do argumento my_list mudou em cada vez que executamos a função sem passar algum valor para ele.

Por que isso acontece?

Isso acontece porque o python processa os valores default de cada argumentos de uma função (ou método) quando essa for definida, após esse processamento o valor é atribuido ao objeto da função. Ou seja, por questões de optimização, seguindo nosso exemplo, o python não cria uma lista vazia para o argumento my_list a cada vez que a função my_function for invocada, ele reaproveita uma lista que foi criada no momento em que essa função foi importada.

>>> my_function.func_defaults
([],)
>>> id(my_function.func_defaults[0])
140634243738080
>>> my_function()
[1]
>>> my_function.func_defaults
([1],)
>>> id(my_function.func_defaults[0])
140634243738080
>>> my_function()
[1, 1]
>>> my_function.func_defaults
([1, 1],)
>>> id(my_function.func_defaults[0])
140634243738080

Note que a identificação do argumento (no caso my_list) não muda, mesmo executando a função várias vezes.

Outro exemplo seria utilizar o resultado de funções como valores default de argumentos, por exemplo, uma função com um argumento que recebe como default o valor de datetime.now().

def what_time_is_it(dt=datetime.now()):
    print(dt.strftime('%d/%m/%Y %H:%M:%S'))

O valor do argumento dt sempre será o datetime do momento em que o python carregou a função e não o datetime de quando a função foi invocada.

>>> what_time_is_it()
07/06/2015 08:43:55
>>> time.sleep(60)
>>> what_time_is_it()
07/06/2015 08:43:55

Isso também acontece com classes?

Sim e de uma forma ainda mais perigosa.

class ListNumbers():
    def __init__(self, numbers=[]):
        self.numbers = numbers

    def add_number(self, number):
        self.numbers.append(number)

    def show_numbers(self):
        print(numbers)

Assim como no caso das funções, no exemplo acima o argumento numbers é definido no momento em que o python importa a classe, ou seja, a cada nova instância da classe ListNumbers, será aproveitada a mesma lista no argumento numbers.

>>> list1 = ListNumbers()
>>> list2 = ListNumbers()
>>> list1.show_numbers()
[]
>>> list2.show_numbers()
[]
>>> list2.add_number(1)
>>> list1.show_numbers()
[1]
>>> list2.show_numbers()
[1]
>>> list1.numbers is list2.numbers
True

Por que isso não acontece com Strings?

Porque strings são imutáveis, o que significa que a cada alteração de valor em uma variavel que armazena uma strings, o python cria uma nova instância para essa variável.

>>> a = 'foo'
>>> id(a)
140398402003832
>>> a = 'bar'
>>> id(a)
140398402003872  # o penúltimo número muda :)

Em argumentos com valores default, não é diferente.

def my_function(my_str='abc'):
    my_str += 'd'
    print(my_str)

No exemplo acima, sempre que for executado o inplace add (+=) será criada outra váriavel para my_str sem alterar o valor default do argumento.

>>> my_function()
abcd
>>> my_function.func_defaults
('abc',)
>>> my_function()
abcd
>>> my_function.func_defaults
('abc',)

Como se proteger?

A maneira mais simples de evitar esse tipo de surpresa é utilizar um valor sentinela como por exemplo None, nos argumentos opcionais que esperam tipos mutáveis:

def my_function(my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(1)
    print(my_list)

Ou, para deixar o código ainda mais elegante, podemos simplificar a condicional com um simples or:

def my_function(my_list=None):
    my_list = my_list or []
    my_list.append(1)
    print(my_list)

Obrigado Bruno Rocha pela sugestão.

Pronto, sem surpresas e sem armadilhas :).

>>> my_function()
[1]
>>> my_function()
[1]
>>> my_function()
[1]

Referências

por Diego Garcia em 07 de June de 2015 às 14:00

June 04, 2015

Osvaldo Santana Neto

Eu e a comunidade Python

Assine a minha newsletter quinzenal O Melhor da Internet e receba um resumo dos melhores materiais sobre Python, Django, Carreira e Empreendedorismo.


O Eric Hideki começou a levantar a história da comunidade Python brasileira e pediu que as pessoas que participaram desde o início pudessem colaborar com o projeto dele.

OBS. Não tive tempo de revisar esse texto antes de publicar. Assim que conseguir um tempinho prometo corrigir os problemas. Até lá, se encontrou algo grave, me manda um email.

Eu e Python

Eu conheci a linguagem Python em 2000 quando trabalhava na Conectiva (criadora do Conectiva Linux). Eu estava trabalhando (em C) num projeto que unificava as configurações de vários gerenciadores de janela suportados pela Conectiva (KDE, Gnome, WindowMaker, etc).

Eu parseava um arquivão de configurações genérico e gerava as configurações para cada um deles.

Fazer isso em C estava dando bastante trabalho e meu chefe (Cavassin) me mostrou a tradução que ele tinha feito de um mini-tutorial de Python do Magnus Lie Hetland.

Levei o artigo pra casa e tentei usar o projeto em que estava trabalhando para aprender a linguagem.

Em uma noite eu consegui implementar em Python tudo o que eu já havia feito em duas semanas de trabalho em C.

Comunidade

Quando eu deixei a Conectiva fui obrigado a trabalhar com Java e não conseguia conceber a razão pela qual as pessoas sofriam tanto com uma linguagem sub-ótima.

Com o passar dos meses eu fui percebendo que as pessoas usavam Java porque várias pessoas também usavam Java: a comunidade Java.

Como criar uma comunidade?

Comecei a pesquisar na internet e encontrei alguns núcleos e pequenos grupos de usuários Python. O mais consistente se encontrava no grupo “python-br” do Yahoo! Groups. Outro grupo que era bem ativo era do TcheZope no RS.

Como eu nunca mexi com Zope resolvi focar em participar da “python-br” cujo administrador “desapareceu” juntamente com o acesso de admin do grupo. Como a gente não tinha o admin desse grupo e começamos a receber muito spam nele decidimos criar a “python-brasil” (ainda no Yahoo! Groups) onde passei a ser o moderador principal (depois recebi ajuda do Pedro Werneck, do Andrews Medina e de mais alguns outros).

Quando eu criei essa lista ela não tinha mais do que 400 assinantes. Quando deixei a moderação ela tinha mais de 3000.

Muitas perguntas que chegavam no grupo eram repetidas e para não ter que ficar respondendo uma por uma achamos melhor criar um site para agrupar o material de Python nacional.

Um dos participantes do grupo (Marco Catunda) criou uma instância com Plone e apontamos um hostname para lá (a gente não tinha domínio próprio ainda). O problema é que ninguém configurou usuários e permissões do Plone corretamente e o Marco andava muito ocupado para fazer isso. Então ficou bem difícil alimentar o site com conteúdo.

Em paralelo a isso eu descobri os Wikis (em especial o MoinMoin que é feito em Python) e resolvi instalar um no provedor onde eu trabalhava. Coloquei alguns artigos que eu havia escrito no site e “lancei” a idéia no grupo que o abraçou. O primeiro site de Python da comunidade brasileira estava no ar. O endereço? http://python.rantac.com.br :)

Como o wiki é livre e, na época, não precisava nem de usuário para colocar ou editar conteúdo a coisa foi crescendo bastante e se tornou o principal site da comunidade…

Não demorou muito para que a gente tivesse motivos para se reunir e conversar sobre Python.

O Rodrigo Senra, que estudava na Unicamp conseguiu o espaço e infraestrutura para um dia de evento: PyConDay… Mas o grande número de palestras submetidas logo demandou mais um dia de evento… E a PyConDay passou a ter dois dias e a se chamar PyConBrasil (posteriormente, por sugestão do Luciano Ramalho renomeamos o evento para PythonBrasil).

O Senra cuidou de tudo praticamente sozinho e se auto-entitulou “Big Kahuna” do evento. Por tradição esse é o título concedido à todos aqueles que se aventuraram na organização de uma PythonBrasil.

Associação

Tudo o que fazíamos, na época, era feito na raça e com recursos próprios. E isso dava um trabalho enorme… Passamos a enfrentar alguns contratempos para organizar os eventos, para manter o site no ar, renovar domínios, etc.

A coisa toda ficou muito individualizada: o Osvaldo moderava a lista, mantinha o domínio pythonbrasil.com em seu próprio cartão (na época precisava ter CNPJ para adquirir um domínio .com.br e/ou ser uma organização sem fins lucrativos para ter um .org.br).

Começamos a esboçar a Associação Python Brasil para dar suporte para a Comunidade. Em 2007, depois de muita cabeçada, idas e vindas, burocracia sem fim (thanks Luciano Ramalho e Dorneles Treméa), fundamos a APyB.

Fundação da APyB

Eu sempre fui conselheiro da APyB e cheguei até a presidi-la por um mandato. É trabalhoso e razoavelmente chato gerir ela. Mas depois que nos acostumamos e ganhamos prática fica até automático.

A Fila Anda

Com o passar dos anos envolvidos com a comunidade eu comecei a ficar um pouco cansado e estava preocupado com a continuidade disso tudo. Eu também achava que novas pessoas surgiriam se eu fosse embora e “liberasse o espaço”.

Outros colegas, aos poucos, foram deixando as alavancas para outras pessoas. Novas lideranças, etc.

Eu acho que a Associação já cumpriu o seu papel. Se existissem pessoas dispostas a cuidar dela de verdade ela até poderia continuar tendo a sua utilidade.

Mas não podemos negar que a internet muda muito rápido e as comunidades ganham características cada vez mais descentralizadas. A importância de uma organização como a APyB claramente diminuiu e isso, na minha opinião, não importa muito.

Mas com o fim da APyB algumas coisas boas produzidas por ela deixarão de existir.

The post Eu e a comunidade Python appeared first on osantana.

por Osvaldo Santana em 04 de June de 2015 às 00:01

May 29, 2015

Gustavo Niemeyer

mgo r2015.05.29

Another release of mgo hits the shelves, just in time for the upcoming MongoDB World event.

A number of of relevant improvements have landed since the last stable release:


New package for having a MongoDB server in test suites

The new gopkg.in/mgo.v2/dbtest package makes it comfortable to plug a real MongoDB server into test suites. Its simple interface consists of a handful of methods, which together allow obtaining a new mgo session to the server, wiping all existent data, or stopping it altogether once the suite is done. This design encourages an efficient use of resources, by only starting the server if necessary, and then quickly cleaning data across runs instead of restarting the server.

See the documentation for more details.

(UPDATE: The type was originally testserver.TestServer and was renamed dbtest.DBServer to improve readability within test suites. The old package and name remain working for the time being, to avoid breakage)

Full support for write commands

This release includes full support for the write commands first introduced in MongoDB 2.6. This was done in a compatible way, both in the sense that the driver will continue to use the wire protocol to perform writes on older servers, and also in the sense that the public API has not changed.

Tests for the new code path have been successfully run against MongoDB 2.6 and 3.0. Even then, as an additional measure to prevent breakage of existent applications, in this release the new code path will be enabled only when interacting with MongoDB 3.0+. The next stable release should then enable it for earlier releases as well, after some additional real world usage took place.

New ParseURL function

As perhaps one of the most requested features of all times, there’s now a public ParseURL function which allows code to parse a URL in any of the formats accepted by Dial into a DialInfo value which may be provided back into DialWithInfo.

New BucketSize field in mgo.Index

The new BucketSize field in mgo.Index supports the use of indexes of type geoHaystack.

Contributed by Deiwin Sarjas.

Handle Setter and Getter interfaces in slice types

Slice types that implement the Getter and/or Setter interfaces will now be custom encoded/decoded as usual for other types.

Problem reported by Thomas Bouldin.

New Query.SetMaxTime method

The new Query.SetMaxTime method enables the use of the special $maxTimeMS query parameter, which constrains the query to stop after running for the specified time. See the method documentation for details.

Feature implemented by Min-Young Wu.

New Query.Comment method

The new Query.Comment method may be used to annotate queries for further analysis within the profiling data.

Feature requested by Mike O’Brien.

sasl sub-package moved into internal

The sasl sub-package is part of the implementation of SASL support in mgo, and is not meant to be accessed directly. For that reason, that package was moved to internal/sasl, which according to recent Go conventions is meant to explicitly flag that this is part of mgo’s implementation rather than its public API.

Improvements in txn’s PurgeMissing

The PurgeMissing logic was improved to work better in older server versions which retained all aggregation pipeline results in memory.

Improvements made by Menno Smits.

Fix connection statistics bug

Change prevents the number of slave connections from going negative on a particular case.

Fix by Oleg Bulatov.

EnsureIndex support for createIndexes command

The EnsureIndex method will now use the createIndexes command where available.

Feature requested by Louisa Berger.

Support encoding byte arrays

Support encoding byte arrays in an equivalent way to byte slices.

Contributed by Tej Chajed.

por niemeyer em 29 de May de 2015 às 12:55

May 28, 2015

Magnun Leno

Hack ‘n’ Cast v0.14 - Projeto MOD

Todo músico que entende um pouco de tecnologia já se irritou com a necessidade de comprar diversos hardwares para melhorar o som produzido pelo seu instrumento. Mas e se existisse um hardware único que pudesse programado e atualizado de forma a atender todas as suas necessidades? Então, agora ele existe...

Baixe o episódio e leia o shownotes

por Magnun em 28 de May de 2015 às 03:11

May 24, 2015

PythonClub

Criação de aplicações no Google App Engine com o Tekton

Google App Engine (GAE)

É a plataforma de Cloud Computing do Google, com ela você pode desenvolver e hospedar aplicações usando Python (2.7) que escalam facilmente, pagando muito pouco por isso.

As desvantagens (em relação a outras plataformas de nuvem, como o Heroku por exemplo) são: - Você terá que desenvolver pensando na plataforma (banco de dados NoSQL, por isso o Django não é recomendável.). - Versão do Python é antiga e não há planos para mudar isso no momento.

Tekton

É um framework para desenvolvimento Web especialmente pensado para uso no Google App Engine. Nele podemos aproveitar o melhor do Django (scaffold, código HTML e validação de formulários a partir de modelos, apps isoladas) sem perder as vantagens que o GAE nos oferece.

Como iniciar

O primeiro passo é baixar o SDK do Google App Engine, com isso pronto podemos começar a conhecer o Tekton.

Em seguida, vamos baixar a aplicação template.

$ wget https://github.com/renzon/tekton/archive/master.zip
$ unzip master && rm master.zip
$ mv tekton-master projeto_appengine && cd projeto_appengine     

Nesse ponto podemos explorar e conhecer a estrutura de diretórios.

└── backend
 ├── appengine
 ├── apps
 ├── build_scripts
 ├── test
 └── venv
$ cd backend/venv/ && ./venv.sh
$ source ./bin/activate         

Com o ambiente virtual pronto, tudo deve estar funcionando. Para testar, vamos utilizar o próprio servidor que vem com o pacote antes de subir parao GAE.

cd ../appengine && dev_appserver.py . 

Tudo certo! Você deve estar vendo o projeto template no seu localhost:8080

Para realizar o deploy no App Engine:

appcfg.py update . --oauth2

Você pode conhecer mais sobre o projeto no Github, no grupo de discussões ou nas vídeo aulas gratuitas no Youtube.

por Guido Luz Percú em 24 de May de 2015 às 03:00

May 18, 2015

Filipe Saraiva

Software Livre no Pint of Science Brasil 2015

Pint of Science é um festival internacional em rede que reúne cientistas em mesas de bares para conversar e compartilhar sobre ciência, a repercussão que sua área de pesquisa tem para a sociedade, e muito mais. É divulgação científica + boteco!

O Brasil está participando pela primeira vez do evento, e a cidade de São Carlos terá 3 dias com mesas de bate-papo sobre temas variados em dois restaurantes da cidade.

Para quem estiver na cidade hoje (18/05), a partir das 20h o Espaço Sete terá uma conversa sobre software livre e a liberdade de conhecimento na academia. Estarei lá junto com um grupo de amigos participantes de diversas comunidades de software livre para falarmos sobre o assunto, e claro, beber cerveja.

Vejo vocês lá!

por Filipe Saraiva em 18 de May de 2015 às 18:32

Galácia

VACAS MAGRAS À VISTA

A economia brasileira está sofrendo um baque como eu nunca tinha visto desde que me entendo por gente. Vamos ter pelo menos mais quatro anos perdidos. Que Deus use tudo isso para trazer o país ao arrependimento.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 18 de May de 2015 às 12:58

May 12, 2015

Eric Hideki

O que você está fazendo de errado na sua carreira de programador

O que você está fazendo de errado em sua carreira de programador

Cada pessoa é um indivíduo único, onde as formas de absorver informações são dos mais variados tipos. Por isso este blog busca diversas formas de ensino, seja através de cursos, tutoriais, artigos ou videoaulas. Mas isso não basta.

O que aprendi sobre aprender

Por que todo mundo está com pressa? E como aprender a programar em 10 anos.

O que está ficando óbvio a cada dia é que poucos sabem os caminhos a serem traçados, seja iniciantes ou quem já está na área há um bom tempo. Isso porque não conseguimos distinguir nossos momentos de escolhas. Mas o que são escolhas?

Como me tornar excelente naquilo que faço?

By Klaus Wuestefeld

1) Torne-se excelente.

Seja realmente bom em alguma coisa. Não fique só choramingando ou querendo progredir às custas dos outros. Não pense q pq vc sentou 4 anos numa faculdade ouvindo um professor falar sobre software q vc sabe alguma coisa. Jogador de futebol não aprende a jogar bola tendo aula. Ele pratica. Instrumentistas geniais nao aprendem a tocar tendo aula. Eles praticam. Pratique. Chegue em casa depois do trabalho e da aula e pratique. No final de semana, pratique.

Crie seu próprio virus, seu próprio jogo, seu próprio SO, seu próprio gerenciador de janelas, seu próprio webserver, sua própria VM, qualquer coisa. Várias coisas.

Não precisa ser só programação. Pode ser networking, vendas, etc. Só precisa ser bom mesmo. Tenha paixão pela coisa.

As melhores praticas do mercado são polinizadas primeiro nos projetos de software livre. Aprenda com eles.

Discípulo, Viajante, Mestre: Primeiro seja um discípulo, tenha mestres locais, aprenda alguma coisa com alguém realmente bom, qq estilo. Depois viaje, encontre outros mestres e aprenda o estilo deles. Por fim, tenha o seu estilo, tenha discípulos, seja um mestre.

Vou fazer o curso da Mary Poppendieck em SP semana q vem e qdo tiver o curso de Scrumban do Alisson e do Rodrigo quero fazer tbem.

“Torne-se excelente” também pode ser chamado de “Melhoria Continua” ou “Learning”.

2) Não seja deslumbrado.

Desenvolvimento de software é a mesma coisa há 60 anos: modelo imperativo. Há 30 anos: orientação a objetos. Bancos de dados relacionais: 30 anos. (“Web”, por exemplo, não é uma tecnologia ou um paradigma. É meramente um conjunto de restrições sobre como desenvolver e distribuir seu software).

Não corra atras da ultima buzzword do mercado. Busque a essência, os fundamentos.

Busque na wikipédia e grokke: determinismo, complexidade de algoritmos “O()”, problema de parada de turing. Pronto, pode largar a faculdade. Falando sério.

Trabalhe com software livre. Não dê ouvidos a grandes empresas, grandes instituições ou grandes nomes só pq são grandes.

Vc acha q vai aprender mais, ter mais networking e mais chance de alocação no mercado trabalhando em par comigo no Sneer por um ano, 8h por semana, ou passando 4 anos na faculdade, 20h por semana, pagando sei la qto por mês?

Vc acha q vai aprender mais trabalhando em par com o Bamboo 6 meses na linguagem boo e na engine do Unity ou fazendo um ano de pós em “a buzzword da moda”?

“Nao seja deslumbrado” tbem é conhecido como “Coolness”.

3) Mantenha-se Móvel.

Com a demanda q temos hoje no mercado, se vc é desenvolvedor de software e n consegue negociar um contrato com uma empresa onde vc é pago por hora e pode trabalhar qtas horas quiser com um minimo de meio periodo, vc precisa rever a sua vida.

É melhor ter dois empregos de meio-periodo q um de periodo integral, pq vc pode largar um deles a qq momento.

Vc nunca vai conseguir nada melhor se não tiver tempo, se não tiver disponibilidade pra pegar algo melhor qdo aparecer.

Vc sustenta seus pais e 7 irmãos? Não. Então para de ser ganancioso e medroso no curto prazo, para de pagar facu, mestrado, pós, MBA, sei-la-o-q e vai aprender e empreender.

Trabalhe remoto. Não é o mais fácil, mas é perfeitamente possível.

Não fique reclamando q está trabalhando demais. Aumente seu preço e trabalhe menos.

4) Emparceire-se Promiscuamente.

Participe de dojos, de congressos, de projetos de software livre. Tenha amigos, colegas, conhecidos. Seja conhecido. Não faça ruído em seis projetos e doze fóruns. Ajude de verdade em um ou dois projetos de cada vez. Ao longo do tempo, vc terá ajudado em vários projetos, trabalhado em varias empresas.

5) Mentalidade de Abundância.

Ajude seus amigos sem cobrar (a “camaradagem” do Vinícius). Dê palestras gratuitas. Cursos gratuitos. Participe de projetos de software livre.

Pare as vezes uma tarde pra receber um amigo seu e explicar seu projeto. Vá visitar seus amigos nos projetos deles. Viaje com algum amigo seu pra visitar um cliente dele, só pra conversar e fazer companhia.

Vc tem um espaço onde dá cursos? É uma Aspercom, Caelum da vida? Chama os brothers p dar curso. Porra, bola um modelo em q as pessoas podem se inscrever para cursos variados, pagando um sinal, e mantém tipo uma agenda pre-combinada: “Será numa terça e quinta a noite, avisadas com duas semanas de antecedencia”. Se rolar, beleza, se depois de meses nao der quorum, devolve o sinal. Pode ser curso de Prevayler, de Kanban, de Scrum, de Lean, de Comp Soberana, de Restfulie, de Cucumber, de Rails, de Teste Automatizado Mega-Avançado, qq coisa.

Chame amigos seus pra dar curso em dupla com vc. Divida clientes.
Divida projetos, mesmo q não precise de ajuda.

Dizia o pai de um brother meu de infância: “Tudo q custa dinheiro é barato.”

6) Busque modelos de custo zero.

Trabalhe em coisas q tem custo administrativo/burocrático/manutenção zero. Por menos ganho q tragam, depois de prontas, estarão tendo uma relação custo/beneficio infinitamente vantajosa.

7) Ganhe notoriedade.

Faça coisas massa. Participe de projetos de software livre. Dê palestras gratuitas. Promova eventos (dojos, debates, grupos de usuários, etc).

By Dairton Bassi:

8 – Não tenha medo!

Meta a cara. Arrisque empreender. Arrisque inovar. O que você tem a perder? No máximo um emprego, mas isso pode ser revertido facilmente em um mercado aquecido como o atual. O pior que pode acontecer é não dar certo. Mesmo assim você terá aprendido muito mais do que batendo cartão.
Saia da zona de conforto. Se o seu trabalho estiver fácil e sob controle, isso significa que ele não está mais agregando para a sua evolução técnica e pessoal.

Não desperdice a chance de trocar de função se a nova oportunidade for mais desafiadora. Isso fará você crescer tecnicamente e o preparará para desafios maiores ainda. Conhecer pessoas novas é tão importante quanto manter-se em contato com código.

Não se detenha por insegurança ou pela sensação de despreparo. Como você acha que vai ganhar experiência em alguma coisa se sempre adiá-la?

Deu para pegar algumas sacadas?

Não esqueça de deixar nos comentários o que descobriu. :)


por Eric Hideki em 12 de May de 2015 às 01:25

May 11, 2015

Ricbit

A Intuição do Knuth

Às vezes eu me pergunto se as pessoas da minha área têm noção de quão sortudos nós somos. Os físicos adorariam viajar no tempo para conversar com o Newton, os matemáticos adorariam conversar com o Euclides, os biólogos adorariam conversar com o Darwin. Mas nós podemos conversar com o Knuth!


Nós temos a sorte de viver no mesmo período de tempo que o criador da análise de algoritmos, que é uma das bases da Ciência da Computação. Se você gosta do assunto, vale a pena juntar uns trocos e viajar até a Califórnia para assistir a uma das palestras dele (dica: todo fim de ano, inspirado nas árvores de Natal, ele faz uma palestra de estrutura de dados, falando sobre árvores; elas também estão online se você não tiver como ver ao vivo).

Eu fiz a peregrinação em 2011, quando consegui assistir a uma das palestras dele. Aproveitei para ir todo contente pegar minha recompensa por ter achado um erro no Art of Computer Programming, mas ele, marotamente, me disse que aquilo que eu achei não era um erro, era uma pegadinha, e eu caí! (Mas eu não vou falar qual a pegadinha, vá na página 492 do TAOCP volume 4A, primeira edição, e confira você mesmo :)

Eu e Knuth, o trollzinho

Nesse dia perguntaram que opinião ele tinha sobre o problema mais difícil da nossa geração, P=NP. A intuição dele é que provalmente é verdade, mas ele acredita que se acharmos a demonstração, ela vai ser não-construtiva. O que isso significa? O que é uma demonstração não-construtiva?

Demonstrações construtivas e não-construtivas


Em análise de algoritmos, as demonstrações construtivas são as mais comuns. Por exemplo, digamos que eu quero provar que é possível calcular x elevado a y em tempo O(y). Isso é fácil, basta construir um algoritmo assim:
E se eu quiser provar que esse mesmo problema pode ser resolvido em tempo O(log y)? Novamente, tudo que eu preciso fazer é exibir um algoritmo que implemente isso:

(Nesse caso eu também precisaria provar que esse algoritmo é de fato O(log y), já não é óbvio por inspeção). Nos dois casos temos exemplos de demonstrações construtivas: se eu quero provar uma propriedade P, basta exibir um algoritmo que tenha essa propriedade P.

As demonstrações não-construtivas são diferentes. Nelas, eu posso provar a propriedade P sem mostrar o algoritmo, através de alguma propriedade matemática do modelo.

Por exemplo, imagine que eu tenho uma lista ordenada de números. Se eu fizer uma busca binária, posso achar a posição de um número dado com O(log n) comparações. Mas é possível criar um algoritmo mais rápido que isso? Eu digo que não é possível, e para isso vou fazer uma prova não-construtiva de que esse é o mínimo que um algoritmo de busca precisa para funcionar.

A Teoria de Shannon aplicada à busca binária


Para isso eu vou usar a teoria da informação de Shannon. Essa teoria é surpreendentemente intuitiva, e se baseia no conceito de surpresa. Se eu te falar que o céu ficou escuro às 19h, você não vai achar nada de mais, nessa hora o Sol está se pondo, então é natural que o céu fique escuro. Mas e se eu falar que o céu ficou escuro às 10 da manhã? Foi uma tempestade? Um eclipse? A nave do Independence Day?

Intuitivamente, quanto mais surpresos nós ficamos com uma sentença, mais informação ela tem. O Shannon definiu então a quantidade de informação como sendo uma função monotônica da probabilidade do evento acontecer:

I(m)=\log\left(\frac{1}{p(m)}\right)

Se o evento é raro, tem bastante informação; se o evento é comum, tem pouca informação. A base do logaritmo fornece a unidade de medida, se a base for 2, então a informação é medida em bits.

E quanta informação nós ganhamos com uma comparação? Se a chance de dar verdadeiro ou falso for a mesma, então a chance é p(m)=1/2, logo a informação é I(m)=1. Você ganha exatamente um bit de informação com uma comparação.

Qual o resultado do nosso algoritmo de busca? O resultado é um índice, se nós temos n elementos no vetor, então a resposta é um índice que varia de 0 a n-1. Logo, a probabilidade de você escolher o índice certo ao acaso é p(m)=1/n, já que a escolha é uniforme.

Quanta informação tem essa escolha, então? Fazendo a conta:


Se você precisa de log n bits para descrever a resposta, e você ganha só 1 bit por comparação, então não tem como um algoritmo rodar em menos que O(log n): a informação tem que vir de algum lugar! Com isso, nós mostramos que qualquer algoritmo precisa rodar no mínimo em tempo O(log n), e sem precisar mostrar o algoritmo em si. Essa é uma demonstração não-construtiva.

Pressinto a pergunta: "mas RicBit, e a busca com hash table, ela não é O(1)?". Sim, ela é! Mas ela não usa comparações, e a nossa análise foi exclusivamente para métodos baseados em comparações. Com um acesso a uma hash você pode ganhar mais que 1 bit de informação por operação.

O limite da ordenação


Um outro exemplo é achar o limite dos algoritmos de ordenação. Suponha que eu tenho um vetor com elementos bagunçados e quero ordená-los usando comparações. Eu sei que cada comparação ganha 1 bit de informação, então só preciso saber quanta informação tem na saída.

Qual o resultado do algoritmo? Um vetor ordenado. Mas os valores do vetor em si são irrelevantes, o que importa mesmo é saber a ordem relativa entre eles. Essa ordem relativa pode ser expressa como uma permutação dos itens originais.

Quantas permutações existem? Se o vetor tem tamanho n, então existem n! permutações, logo a probabilidade é 1/n!. Fazendo as contas:

\begin{align*}I(m)&=\log\left(\frac{1}{p(m)}\right)=\log\left(1/\frac{1}{n!}\right)=\log \left(n!\right)\\&\sim\log\left(n^n e^{-n}\sqrt{2\pi n}\right)\\&\sim n\log n-n-\frac{1}{2}\log\left(2\pi n\right)\\&\sim O(n \log n)\end{align*}

Primeiro você usa a aproximação de Stirling, depois joga fora todos os termos assintoticamentes menores que o dominante. O resultado é que nós provamos que nenhuma ordenação pode ser melhor que O(n log n), sem precisar mostrar nenhum algoritmo!

Novamente, esse resultado só vale para ordenações baseadas em comparações. Sem usar comparações, você tem métodos como radix sort e ábaco sort que são melhores que O(n log n).

A análise por quantidade de informação


Esse método de análise da quantidade de informação pode ser utilizado em qualquer algoritmo, desde que você note um detalhe muito importante: o método acha um limite inferior para a complexidade, mas não prova que esse algoritmo existe! Tudo que conseguimos provar como ele é que, se o algoritmo existir, então ele não pode ser melhor que o limite achado.

por Ricardo Bittencourt (noreply@blogger.com) em 11 de May de 2015 às 19:35

May 10, 2015

PythonClub

Como otimizar suas consultas no Django - De N a 1 em 20 minutos

Essa semana fiz uma palestra em um BEV no Luizalabs. Resolvi falar sobre Django, pois é um framework que utilizamos na empresa para diversos projetos.

O objetivo é ensinar algumas técnicas simples e que auxiliam a diminuir o número de consultas que realizamos no banco de dados.de

Os slides podem acessados aqui.

Então, vamos lá!

Overview

Geralmente nossa aplicação Django tem um arquivo models.py, que contém nossa representação das tabelas no banco de dados.

Para os próximos exemplos considere esse arquivo:

from django.contrib.auth.models import User
from django.db import models

class Cadastro(models.Model):
    # chave estrangeira para o usuário
    user = models.OneToOneField(User)

    # Outros campos
    # [...]

Veja o exemplo abaixo, é muito comum ver algo parecido em algum tutorial sobre Django.

>> Cadastro.objects.all()

Mas o que realmente acontece quando fazemos isso?

Para que a consulta aconteça, 5 elementos principais precisam interagir entre si. Os elementos são:

Model
Manager
QuerySet
Query
SQLCompiler

É importante entender o papel de cada um, para que sejamos capazes de atuar com assertividade.

Model
  • É uma representação da nossa tabela de dados, contém os campos e os comportamentos dos dados que estamos armazenando.
Manager
  • Está sempre acoplado a um model e é responsável por expor os métodos do QuerySet. Quando não declaramos nenhum manager, o Django cria por padrão o objects.
QuerySet
  • QuerySet é um conjunto de ações que serão realizadas no banco de dados (select, insert, update ou delete). Responsável por interagir diretamente com a Query.
Query
  • Cria uma estrutura de dados complexa com todos os elementos presentes em uma consulta. Gera uma representação SQL de um QuerySet.
SQLCompiler
  • Recebe as instruções SQL e realiza as operações no banco de dados.

Agora que conhecemos os 5 elementos principais, vamos falar sobre QuerySet, é com ele que vamos conseguir construir queries mais eficientes.

QuerySets são Lazy

Algo que é importante notar sobre o comportamento das QuerySets, são que elas são Lazy.

Mas o que é isso?

Imaginem as seguintes consultas:

>> cadastros = Cadastro.objects.all()
>> ativos = cadastros.filter(ativo=True)
>> inativos = cadastros.filter(inativo=True)

Sabe quantas consultas foram realizadas no banco de dados, por essas 3 linhas de código? NENHUMA. QuerySets podem ser:

  • Construídas
  • Filtradas
  • Limitadas
  • Ordenadas
  • Passadas comoo parâmetro

E nenhuma consulta será realizada no banco de dados.

Quando dizemos que as QuerySets são lazy, queremos dizer que as consultas só serão realizadas no banco de dados, quando pedimos!

Então, como pedimos?

# Quando solicitamos somente um resultado
>> Cadastro.objects.all()[0]

# Quando fazemos um slicing passando o parâmetro `step`
>> Cadastro.objects.all()[::2]

# Quando fazemos uma iteração
>> [cadastro for cadastro in Cadastro.objects.all()]

# Quando chamamos o método len()
>> len(Cadastro.objects.all())

# Quando chamamos o método list()
>> list(Cadastro.objects.all())

 # Quando chamamos o método bool()
>> bool(Cadastro.objects.all())

# Quando chamamos o método repr()
>> repr(Cadastro.objects.all())

Uma vez que entendemos como as consultas são realizadas no banco de dados, vamos aprender como resolver os problemas mais comuns quando se trata de consultas: relacionamentos.

Relacionamento OneToOne e ForeignKey

OneToOne e ForeignKey são os tipos de relacionamentos mais comuns no Django, estamos utilizando-os quase intuitivamente.

Imaginem o seguinte cenário:

Temos um loop e a cada iteração invocamos um atributo do models que é uma chave estrangeira para outra tabela.

>> cadastros = Cadastros.objects.all()
>> cadastros.count()
500 # Temos 500 cadastros no nosso banco de dados

# Fazemos uma iteração em todos os cadastros
>> for cadastro in cadastros:
    # realizamos um print com o nome do usuário para tal cadastro.
    # note que essa poderia ser qualquer outra operação, onde o atributo `user` fosse acessado
    print cadastro.user

Esse é um código simples e que geralmente não vemos problemas nenhum, mas iremos nos supreender com quantas queries são realizadas no banco de dados.

# https://docs.djangoproject.com/en/1.8/faq/models/#how-can-i-see-the-raw-sql-queries-django-is-running
>> from django.db import connection

>> cadastros = Cadastros.objects.all()

>> for cadastro in cadastros:
    print cadastro.user

>> print len(connection.queries)
501

Foram realizadas 501 consultas para iterar sobre 500 cadastros (1 consulta para retornar todos os cadastros e 1 consulta para cada vez que acessamos o atributo user). Isso ocorre, porque estamos acessando um atributo que é um relacionamento para outra tabela, cada vez que o Django acessa esse atributo uma nova consulta precisa ser realizada no banco de dados.

Isso é válido tanto para OneToOne e ForeignKey.

Como podemos resolver isso? Utilizando o método do QuerySet chamado select_related.

Relacionamento reverso

Por padrão o Django adiciona um relacionamento reverso quando sua tabela é referenciada por uma chave estrangeira.

Se não passar o parâmetro related_name, irá seguir o padrão <nome_tabela>_set

from django.contrib.auth.models import User
from django.db import models

class Cadastro(models.Model):
    user = models.OneToOneField(User)

    # Outros campos
    # [...]

class Endereco(models.Model):
    cadastro = models.ForeignKey(Cadastro)

    # Outros campos
    # [...]

Dessa forma, criamos um relacionamento reverso no model Cadastro, quando referenciamos ele numa chave estrangeira no model Endereco.

>> cadastros = Cadastro.objects.all()

>> for cadastro in cadastros:

    # Uma vez que o relacionamento foi criado, podemos acessá-lo
    print cadastro.endereco_set.all()

Se houvesse o parâmetro related_name, acessariamos pelo nome que criamos.

class Endereco(models.Model):
    cadastro = models.ForeignKey(Cadastro, related_name='enderecos')

    # Outros campos
    # [...]


>> cadastros = Cadastro.objects.all()
>> for cadastro in cadastros:
    # Acessando através do related_name
    print cadastro.enderecos.all()

Relacionamentos reversos não são possíveis com o select_related, por isso criou-se a partir da versão 1.4 o método prefetch_reĺated.

Inserir dados

Um problema para inserir dados é quando precisamos iterar sobre um conjunto grande de informações e criar um registro para cada linha, usos comum para importações e logs.

>> from django.db import connection
>> nomes = [
    'Lucas', 'Teste 01', 'Teste 02', 'Nome 3', # 1000 nomes no total
]

# Inserimos um cadastro para cada nome que existe na nossa variável `nomes`
>> for nome in nomes:
    Cadastro.objects.create(nome=nome)

>> print len(connection.queries)
1000

E acessamos 1000 vezes o banco de dados para criar todos os cadastros. Existe um método chamado bulk_create, que resolve nosso problema.

>> from django.db import connection
>> nomes = [
    'Lucas', 'Teste 01', 'Teste 02', 'Nome 3', # 1000 nomes no total
]

>> cadastros = []
>> for nome in nomes:
   cadastro = Cadastro(nome=nome)
   cadastros.append(cadastro)

# Insere todos os cadastros de uma só vez
>> Cadastro.objects.bulk_create(cadastros)
>> print len(connection.queries)
1

O bulk_create recebe uma lista de cadastros e cria realizando somente uma query. É bom notar que cada item dentro da variável cadastros é uma representação do modelo de Cadastro.

Não funciona para relacionamentos ManyToMany e que os signals do Django pre_save e post_save não serão chamados, pois o método save não é utilizado nesse caso.

Atualizar dados

Muitas vezes precisamos atualizar um conjunto de dados e fazemos isso através de uma iteração sobre cada objeto e alterando o campo que desejamos.

>> from django.db import connection

>> cadastros = Cadastro.objects.all()

>> for cadastro in cadastros:
    cadastro.notificado = True
    cadastro.save()

>> print len(connection.queries)
501 # 1 consulta para retornar os cadastros e 1 para cada item no loop

E cada vez que chamamos o método save uma nova consulta é realizada.

Para esses casos podemos utilizar o método update.

>> from django.db import connection

>> cadastros = Cadastro.objects.all()

>> cadastros.update(notificado=True)
500 # Retorna a quantidade de itens que foram atualizados

>> print len(connection.queries)
1

O update realiza um SQL Update no banco de dados e retorna a quantidade de linhas que foram atualizados.

Os signals do Django pre_save e post_save não serão chamados, pois o método save não é utilizado nesse caso.

Deletar dados

O mesmo comportamento existe quando estamos removendo alguns dados. Se fosse preciso apagar todos os dados, seria comum se alguém escrevesse assim:

>> from django.db import connection

>> cadastros = Cadastro.objects.all()

>> for cadastro in cadastros:
    cadastro.delete()

>> print len(connection.queries)
501 # 1 consulta para retornar os cadastros e 1 para cada item no loop

Porém, pode-se fazer dessa maneira:

>> from django.db import connection

>> Cadastro.objects.all().delete()

>> print len(connection.queries)
1

QuerySet possui um método chamado delete que apaga todos os dados retornados.

# Apagar somente inativos
>> Cadastro.objects.filter(inativo=True).delete()

# Apagar somente ativos
>> Cadastro.objects.filter(ativo=True).delete()

Deve-se lembrar, que assim como o update e o bulk_create os signals do Django não serão chamados, no caso do delete os signals são pre_delete e pos_delete.

Espero que tenha ajudado, até a próxima!

por Lucas Magnum em 10 de May de 2015 às 16:55

May 08, 2015

Galácia

Não há oposição entre conhecimento das Escrituras e fogo do Espírito. Por isso as Sagradas Letras ensinam: "Mas quando o Espírito da verdade vier, ele vai guiar vocês a toda a verdade" (Jo 16.13a).

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 08 de May de 2015 às 12:27

May 07, 2015

Galácia

Lições da Minha Geração: Impérios e Teorias Econômicas

Vivi o bastante ver que um império econômico de uma empresa não dura para sempre. A Microsoft se ergueu e se tornou um imenso monopólio imbatível de software, mas olhei novamente e vi dois gigantes se levantarem rapidamente e tomar o lugar dela: Google e Facebook. Um terceiro também se levantou, mas este não era tão novo quanto os dois primeiros: a Apple — uma azarona, vinha sempre em segundo

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 07 de May de 2015 às 00:24

May 06, 2015

Galácia

Sobre Graça e Desobediência

Embora a salvação de Israel fosse um dom de pura graça e não pudesse ser negociada, ela podia, contudo, ser perdida pela desobediência. — Paul Hoff, O Pentateuco

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 06 de May de 2015 às 20:16

Aprenda Python

Solução do desafio

Eis aqui duas soluções para o exercício de Python que seu professor passou. 1) Versão resumida e malcriada. print("Estude!") 2) Versão extendida. Estude. Vá por mim: gaste tempo com tutoriais. A internet está cheio deles. Dúvidas, todos nós temos. Ninguém nasceu sabendo. Nem seu professor. Mas só dá pra ter dúvida sobre o que já tentamos resolver. Antes disso, é desconhecimento mesmo.

por Vinicius Assef (noreply@blogger.com) em 06 de May de 2015 às 03:41

AboutWilson.net

Captura de dados da Corrida de São Silvestre com Python—Parte 3

Dando sequência a série de posts onde eu faço a análise do dataset de campeões da Corrida de São Silvestre, vou desenvolver a análise exploratória através de gráficos que me ajudam e compreender melhor os dados e a levantar algumas questões interessantes como o desempenho da participação dos quenianos a partir da década de 90.

Mostro como este dataset foi construído no post Captura de dados da Corrida de São Silvestre com Python—Parte 1 e faço o tratamento e limpeza dos dados no post Captura de dados da Corrida de São Silvestre com Python—Parte 2.

Lembrando que o objetivo disso tudo é entender como o clima pode influenciar o desempenho dos corredores. Na Parte 2 dessa sequência eu criei a variável pace mas não disse porque. O pace é uma medida relativa que relaciona o percurso com o tempo, ou seja, é uma forma diferente de expressar a velocidade do corredor, também poderia ter utilizado a velocidade em km/min ou km/h, mas o pace é mais comum entre os corredores. Não poderia utilizar apenas o tempo porque o ele depende do percurso, e quanto maior o percurso maior o tempo, logo isso compromete qualquer comparação que eu queira fazer. A idéia neste post é explorar os dados, entender o seu comportamento e como posso trabalhar com eles para tentar responder a pergunta colocada. Para isso eu vou observar o comportamento do pace e verificar como ele se dá quando considero o sexo, mas antes vou apresentar uma contagem simples dos dados dos campeões que mostra como é possível extrair informações interessantes de um dataset simples como este.

In [1]:
%pylab inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import statsmodels.api as sm
import seaborn as sb
sb.set_context("talk")
import sys
print('python', sys.version)
print('pandas', pd.__version__)
print('statsmodels', sm.version.full_version)
Populating the interactive namespace from numpy and matplotlib
python 3.4.1 (default, May 19 2014, 13:10:29) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)]
pandas 0.16.0
statsmodels 0.6.1

Carregando os dados limpos e formatados

Começo carregando o arquivo CSV saosilvestre-lf.csv que são os dados limpos e formatados produzidos no último post. O dataset está limpo e formatado, os campos de data já estão no formato ISO e as colunas tempo e pace estão em decimais que representam os minutos.

In [2]:
ss = pd.read_csv("https://raw.githubusercontent.com/wilsonfreitas/saosilvestre/master/saosilvestre-lf.csv")

Vou remover as colunas: largada, chegada e horario; elas não vão me ser úteis aqui e além do mais poluem a vizualização.

In [3]:
ss = ss.drop(['largada', 'chegada', 'horario'], 1)
ss.head()
Out[3]:
nome pais corrida ano tempo percurso data pace sexo
0 Alfredo Gomes Brasil 1 1925 23.166667 6200 1925-12-31 12:00:00 3.736559 masculino
1 Jorge Mancebo Brasil 2 1926 22.533333 6200 1926-12-31 12:00:00 3.634409 masculino
2 Heitor Blasi Itália 3 1927 23.000000 6200 1927-12-31 12:00:00 3.709677 masculino
3 Salim Maluf Brasil 4 1928 29.183333 8800 1928-12-31 12:00:00 3.316288 masculino
4 Heitor Blasi Itália 5 1929 29.183333 8800 1929-12-31 12:00:00 3.316288 masculino

Explorando os dados

O dataset tem registros de campeões da Corrida de São Silvestre desde 1925, acredito que o primeiro ano da prova, com o tempo, sexo, país, distância do percurso e ano. Quando eu pego um dataset eu gosto de contar ocorrências, montar um histograma das variáveis, ou seja, entender o que eu tenho em mãos.

Dessa maneira a primeira ideia é contar a quantidade de campeões por país, ou seja, fazem um histograma por pais que seria uma variável categórica. No entanto, tenho a coluna sexo e gostaria de ver essa contagem agrupada por sexo. Gostaria ainda que em caso de empate, o país com maior quantidade de campeões masculinos viesse na frente.

Para fazer isso com o pandas eu preciso agrupar os dados por pais e sexo, fazer a contagem da variável sexo, isto é, sexo por país, calcular o total de campeões somando as quantidade de campeões por sexo e finalmente ordenar pelo total e pela quantidade de campeões homens antes de fazer o gráfico.

In [4]:
ss_pais = ss.groupby(['pais', 'sexo'])\
    .sexo\
    .count()\
    .unstack()\
    .fillna(0)
ss_pais['total'] = ss_pais['masculino'] + ss_pais['feminino']
ss_pais.sort(['total', 'masculino'], inplace=True)
ss_pais[['masculino', 'feminino']].plot(kind='bar', stacked=True);

Este é o gráfico com as quantidades agrupadas por sexo empilhadas, que apresenta exatamente um histograma da quantidade de campeões por país, trazendo a separação por sexo. Mas se as barras fossem de apenas 1 cor eu teria apenas o histograma de campeões.

O desempenho do Brasil é bom porque tem a maior taxa de participação na prova, diferente do Quênia que começou a marcar presença recentemente.

Outra forma de olhar o mesmo gráfico é colocando as barras lado a lado e assim é possível observar que apenas Portugal e Alemanha possuem mais campeãs que campeões e que México, Etiópia e Estados Unidos possuem quantidades iguais de campeões por sexo. Novamente fica claro que o Brasil possui um número excepcional de campeões porque realiza essa prova desde 1925 e se separar este gráfico por sexo, no feminino o Brasil cai para a terceira posição.

In [5]:
ss_pais[['masculino', 'feminino']].plot(kind='bar', stacked=False);

Evolução dos campeões ao longo dos anos

Outra coisa interessante de fazer é avaliar a evolução dos campeões por país ao longo dos anos. A ideia é fazer a contagem acumulada dos campeões ao longo dos anos.

In [6]:
ss.groupby(['ano', 'pais'])\
    .corrida\
    .count()\
    .unstack()[['Brasil', 'Quênia']]\
    .fillna(0)\
    .cumsum()\
    .plot();

Observando o gráfico acima vemos que o Brasil ficou quase 3 décadas sem campeões, voltando a acumular vitórias nos anos 80. Quênia começou a colecionar vitórias na década de 90 e desde então vem em um crescente aumento de vitórias. Observando as tendências destas curvas vejo que o coeficiente de crescimento do Quênia é maior do que do Brasil, indicando que em algum momento este país ultrapassará o Brasil em quantidade de campeões da corrida.

Vou separar os dados de Brasil e Quênia a partir de 1990, ano em que Quênia começou a ter vitórias, e tentar fazer uma previsão do ano em que o Quênia ultrapassará o Brasil em quantidade de vitórias, com base nestas tendências. Dessa forma vou ficar com 2 datasets e vou ajustar uma reta para cada conjunto de dados. O objetivo é extrapolar a tendência de vitórias dos países e tentar prever o ano em que as retas se cruzam, indicando que o Quênia atingiu a mesma quantidade de vitórias do Brasil.

In [7]:
ss_vic = ss.groupby(['ano', 'pais'])\
    .corrida\
    .count()\
    .unstack()\
    .fillna(0)\
    .cumsum()

ss_vic_br = ss_vic.loc[ss_vic.index > 1990, 'Brasil']
ss_vic_qn = ss_vic.loc[ss_vic.index > 1990, 'Quênia']

def fit(x, y):
    X = sm.add_constant(x)
    model = sm.OLS(y, X)
    return model.fit()

fit_br = fit(ss_vic_br.index.values, ss_vic_br.values)
fit_qn = fit(ss_vic_qn.index.values, ss_vic_qn.values)

O ajuste das retas me dá os coeficientes das equações do primeiro grau que representam as vitórias acumuladas em função dos anos. Para saber o ano em que Quênia ultrapassará o Brasil é necessário igualar as equações e calcular o ano.

In [8]:
diff = fit_br.params - fit_qn.params
print("Ano = {0}".format(int(-diff[0]/diff[1])))
Ano = 2035

De acordo com as retas ajustadas o ano será próximo de 2035. Ainda poderíamos incluir a variância dos coeficientes na conta e estimar a incerteza sobre esta estimativa.

Apenas para melhor ilustrar o que acabei de calcular vou criar um gráfico com os pontos e as retas e extrapolar as retas até 2040 para observar o ponto de cruzamento.

In [9]:
fig, ax = plt.subplots(figsize=(12,6))

x, y = fit_br.model.data.exog[:,1], fit_br.model.data.endog
ax.plot(x, y, 'ro', label="Brasil")

x = np.arange(1990, 2040)
y = fit_br.params[0] + fit_br.params[1]*x
ax.plot(x, y, 'r-')

x, y = fit_qn.model.data.exog[:,1], fit_qn.model.data.endog
ax.plot(x, y, 'go', label="Quênia")

x = np.arange(1990, 2040)
y = fit_qn.params[0] + fit_qn.params[1]*x
ax.plot(x, y, 'g-')

ax.axvline(2035, color='grey', linestyle='dashed')

ax.legend(loc='best');

Como é possível observar, as retas cruzam-se próximo de 2035.

Conclusão

Foi possível observar com este simples dataset como utilizar ferramentas de visualização e regressão para extrair um pouco do que os dados tem a dizer. Consegui enxergar a distribuição de campeões de 2 formas diferentes, podendo assim identificar aspectos diferentes na distribuição de campeões. A análise de evolução dos dados permitiu fazer uma previsão, onde considerando o histórico observado foi possível prever que próximo de 2035 teremos o Quênia com uma maior quantidade de vitórias na corrida de São Silvestre, obviamente se estas tendências se mantiverem.

Gosto de ver como é possível extrair informações relevantes com análises simples em datasets que cabem na memória do computador. Essa abordagem pode ser reproduzida mesmo para grandes conjuntos de dados onde uma amostra pode ser separada e analisada independentemente. A idéia de trabalhar com conjuntos de dados gigantes é um passo posterior, quando algumas hipóteses já foram levantadas em amostras menores. Para explorar os dados ferramentas visuais são muito interessantes, tem muita gente gerando bons resultados com Excel, eu particularmente não gosto. Na análise de dados é preciso ter parsimônia para saber interpretar o que os dados têm a dizer.

por Wilson Freitas em 06 de May de 2015 às 03:00

April 30, 2015

Galácia

A verdade é que se alguém não é uma bênção onde está, será uma maldição aonde quer que vá. — Erlo Stegen, Avivamento na África do Sul

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 30 de April de 2015 às 11:41

Governabilidade jamais justifica roubalheira. Não importa o partido.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 30 de April de 2015 às 11:38

April 29, 2015

Galácia

De Quem Era o Sangue na Cruz?

[...] para pastorearem a igreja de Deus, que ele comprou com o próprio sangue dele. Atos 20.28.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 29 de April de 2015 às 19:00

April 23, 2015

Filipe Saraiva

Cantor no KDE Applications 15.04

Com o lançamento do KDE Applications 15.04, o segundo release no novo modelo de lançamentos de softwares desenvolvidos no KDE – agora o desktop, conjunto de aplicações, e frameworks tem cada um seu próprio ciclo de release -, o software para programação científica Cantor chegou com várias novidades. Esse lançamento me deixa particularmente feliz pois trabalhei bastante em algumas delas. =)

Vamos ver o que o Cantor tem de novo?

Cantor portado para Qt5/KF5

cantor-kf5

Cantor Qt5/KF5 – visual usando Breeze, o novo tema padrão do KDE. Na imagem é possível ver o terminal, painel de gerenciamento de variáveis, destaque de sintaxe, complementação de código, e botões da tela padrão.

Trabalho que comecei no LaKademy do ano passado e fui desenvolvendo desde aquela data. Devo ter feito commits partindo de uns 5 países diferentes durante esse tempo.

A transição para essa nova tecnologia foi realizada com sucesso e até o momento não notamos nenhuma funcionalidade perdida ou bug crítico introduzido. Todos os backends e plugins foram portados, e alguns bugs que surgiram durante o port foram corrigidos.

Evidente que isso não garante que o software esteja livre de erros, portanto pedimos aos utilizadores que reportem quaisquer problemas no nosso gerenciador de bugs. De qualquer forma, o software está bastante estável.

Usuários do Cantor da versão Qt4 terão suas configurações migradas para o novo formato utilizado na versão Qt5/KF5 automagicamente após a primeira inicialização.

Backend para Python 3

Durante o Season of KDE 2014 orientei o colaborador Minh Ngo no projeto de desenvolvimento do backend para Python 3, fazendo com que o Cantor atingisse a marca de 10 backends diferentes!

cantor-backends

Tela de seleção de backend: Python 3 e seus outros nove irmãos

O backend de Minh utiliza comunicação via D-Bus para ligar o Cantor ao Python 3, uma arquitetura diferente da utilizada no Python 2 mas que já foi utilizada em outros backends, como no R.

O bacana é que agora o Cantor pode agradar tanto os pythonistas que usam Python 2 quanto os que já utilizam Python 3. Esperamos receber o feedback de vocês!

Ícone!

Cantor foi lançado originalmente em 2009, no agora velhinho KDE SC 4.4. Desde aquela época ele nunca teve um ícone próprio.

O lançamento da versão Qt5/KF5, que marca uma mudança substancial no desenvolvimento da aplicação, é um bom momento para também lançar um ícone próprio para o software, dando uma cara para ele.

Ícone do Cantor

Ícone do Cantor

E o resultado ficou excelente! Mostra bem a ideia do Cantor: um quadro negro para você ficar desenvolvendo seus cálculos enquanto coça a cabeça e pensa “e agora, daqui vai para onde?”. =)

Obrigado a Andreas Kainz e Uri Herrera, membros do VDG que desenvolveram o ícone!

Outras alterações e bugs corrigidos

Boa parte dos bugs introduzidos durante o processo de porting pro Qt5/KF5 foram corrigidos antes do release.

Há também algumas alterações menores que merecem ser citadas, como a mudança da categoria KNewStuff de “Python2″ para “Python 2″ e a adição da categoria “Python 3″; remoção do carregamento automático do módulo pylab; agora é possível executar comandos do Python com comentários; entre outras.

Para o log completo dos commits incluídos nesta versão, veja esta página.

Futuro

Para o futuro talvez o plano de maior prioridade seja remover a KDELibs4Support do Cantor. O Lucas já fez parte desse trabalho, e esperamos finalizá-lo para o próximo release.

Eu pretendo dar uma olhada na comunicação via D-Bus e verificar se ela seria uma boa saída para o backend do Scilab. Outra tarefa também programada é a reorganização dos assistentes para geração de gráficos nos backends do Python. E um objetivo de longo prazo é acompanhar a criação do projeto Jupyter, que será o futuro do IPython notebooks – tornar o Cantor compatível com o Jupyter pode ser uma boa forma de aumentar o número de potenciais usuários do software, além de fomentar a colaboração entre diferentes comunidades com interesse em programação científica.

Também irei aproveitar o lançamento dessa versão e escrever sobre duas formas de utilizar o Cantor – estilo terminal como o Matlab; e estilo notebooks, como o IPython. Aguardem!

Se você gostaria de auxiliar no desenvolvimento do Cantor, entre em contato para conversarmos sobre resoluções de bugs, desenvolvimento de novas funcionalidades, e mais. Ou contribua com a vakinha do KDE Brasil para realização do LaKademy 2015. Minha participação no evento será bastante focada no desenvolvimento do software, principalmente nos objetivos que listei acima.

por Filipe Saraiva em 23 de April de 2015 às 13:21

April 22, 2015

Magnun Leno

Hack ‘n’ Cast v0.13 - Hack ‘n’ Drops #001

Microsoft OpenSource, Netflix 8bits, detentos hackers e seu imposto de renda são assuntos hoje no Hack 'n' Cast.

Baixe o episódio e leia o shownotes

por Magnun em 22 de April de 2015 às 02:12

April 18, 2015

Kodumaro

Tipos em Cython

Ontem fiz uma pequena introdução ao Cython.

Cython é uma plataforma que traduz código Python para C e o compila em biblioteca compartilhada importável no próprio Python. A linguagem em si é um superset de Python, com tipagem estática ou dinâmica (duck-typing) e suporte a código especial que pode ser traduzido diretamente para C.

Uma parte importante de Cython é sua tipagem estática, mas os tipos pode ser um pouco diferentes de Python.

Há tipos específicos, como struct e enum, que são traduzidos diretamente para o equivalente C, e tipo de extensão (cdef class). Entre eles:

Tipo CythonTipo CCoerção para Python 3
boolPyLongObject *bool
bintintbool
size_tsize_tint
charcharint
unsigned charunsigned charint
intintint
longlongint
long longlong longint
floatfloatfloat
doubledoublefloat
long doublelong doublefloat
const char *const char *bytes
bytesPyBytesObject *bytes
const Py_UNICODE *const Py_UNICODE *str
unicodestruct PyUnicodeObjectstr
objectPyObject *object
listPyListObject *list
dictPyDictObject *dict
setPySetObject *set
tuplePyTupleObject *tuple
void *void *sem equivalência
struct Sstruct Sdict
enum Eenum Eint

Todos os modificadores C (unsigned, const, long, *…) são aceitos. Na coerção de tipos, também é aceito &. Se um valor numérico for recebido por uma variável do tipo object, será usado PyLongObject * (inteiro de tamanho arbitrário) ou PyFloatObject * (ponto flutuante, equivalente a double de C).

[]’s
ℭacilhας, La Batalema

por noreply@blogger.com (ℭacilhας, ℒa ℬatalema) em 18 de April de 2015 às 23:08

Aspectos – parte I

Um paradigma muito útil é a Programação orientada a Aspectos.

Consiste em separar e encapsular as funcionalidades de um código conforme sua importância.

Nesta primeira parte, abordaremos de forma simples tal separação e deixaremos o conceito de mixins para a parte II.

Vamos começar com um exemplo: imagine uma view que modifica o estado de um objeto, retornando um hash do novo estado:
@app.route('/people/<uuid>/', methods=['PATCH'])
def update_person(uuid):
person = db.person.find({ '_id': uuid }).first()
if not person:
raise Http404

try:
data = json.loads(request.data)
except ValueError:
return json.dumps({ 'error': 'invalid request' }), \
400, \
{ 'Content-Type': 'application/json' }

person.update(data)
db.person.save(person)

r = [(str(k), repr(v)) for k, v in person.iteritems()]
r.sort()
s = ';'.join('{}:{}'.format(k, v) for k, v in r)

return json.dumps({ 'etag': md5(s).hexdigest() }), \
200, \
{ 'Content-Type': 'application/json' }

A solução atende, mas é de difícil manutenção. Perceba que a função chamada update_person (atualiza pessoa) faz muito mais do que simplesmente atualizar os dados:
  • Recupera o documento do banco, retornando 404 se não existir;
  • Faz os parsing dos dados recebidos, retornando 400 em caso de erro;
  • Efetivamente atualiza o documento;
  • Serializa o objeto para a resposta;
  • Gera um hash da serialização;
  • Responde a requisição com formato conveniente.

Cada um desses passos é um aspecto do processo e pode ser isolado do restante.

Vamos então separar o primeiro aspecto: recuperação do documento.
def retrieve_person_aspect(view):
@wraps(view)
def wrapper(uuid):
person = db.person.find({ '_id': uuid }).first()
if not person:
raise Http404

return view(person)
return wrapper

@app.route('/people/<uuid>/', methods=['PATCH'])
@retrieve_person_aspect
def update_person(person):
try:
data = json.loads(request.data)
except ValueError:
return json.dumps({ 'error': 'invalid request' }), \
400, \
{ 'Content-Type': 'application/json' }

person.update(data)
db.person.save(person)

r = [(str(k), repr(v)) for k, v in person.iteritems()]
r.sort()
s = ';'.join('{}:{}'.format(k, v) for k, v in r)

return json.dumps({ 'etag': md5(s).hexdigest() }), \
200, \
{ 'Content-Type': 'application/json' }

Agora a recuperação do documento está isolada, podendo inclusive ser usada em outras views. Nossa view já recebe o documento recuperado e não precisa lidar com o fato dele existir ou não.

Porém ainda temos muita coisa misturada. Por exemplo, a obtenção e parsing dos dados recebidos: isso caracteriza outro aspecto do código, que não a atualização do documento.

Podemos portanto, separá-los:
def parse_data_aspect(view):
@wraps(view)
def wrapper(person):
try:
data = json.loads(request.data)
except ValueError:
return json.dumps({ 'error': 'invalid request' }), \
400, \
{ 'Content-Type': 'application/json' }

return view(person, data)
return wrapper

def retrieve_person_aspect(view):
...

@app.route('/people/<uuid>/', methods=['PATCH'])
@retrieve_person_aspect
@parse_data_aspect
def update_person(person, data):
person.update(data)
db.person.save(person)

r = [(str(k), repr(v)) for k, v in person.iteritems()]
r.sort()
s = ';'.join('{}:{}'.format(k, v) for k, v in r)

return json.dumps({ 'etag': md5(s).hexdigest() }), \
200, \
{ 'Content-Type': 'application/json' }

A função update_person já está muito mais limpa: atualiza o documento, serializa e retorna o hash, mas ainda faz coisas demais. Vamos separar o tratamento do retorno:
def respond_etag_aspect(view):
@wraps(view)
def wrapper(person, data):
response = view(person, data)
return json.dumps({ 'etag': md5(response).hexdigest() }), \
200, \
{ 'Content-Type': 'application/json' }
return wrapper

def parse_data_aspect(view):
...

def retrieve_person_aspect(view):
...

@app.route('/people/<uuid>/', methods=['PATCH'])
@retrieve_person_aspect
@parse_data_aspect
@respond_etag_aspect
def update_person(person, data):
person.update(data)
db.person.save(person)

r = [(str(k), repr(v)) for k, v in person.iteritems()]
r.sort()
return ';'.join('{}:{}'.format(k, v) for k, v in r)

As coisas estão ficando cada vez mais separadas. A única coisa que a função update_person faz agora além de atualizar o documento é serializá-lo. Isso também pode ser isolado:
def serialize_person_aspect(view):
@wraps(view)
def wrapper(person, data):
response = view(person, data)
r = [(str(k), repr(v)) for k, v in response.iteritems()]
r.sort()
return ';'.join('{}:{}'.format(k,v) for k, v in r)

def respond_etag_aspect(view):
...

def parse_data_aspect(view):
...

def retrieve_person_aspect(view):
...

@app.route('/people/<uuid>/', methods=['PATCH'])
@retrieve_person_aspect
@parse_data_aspect
@respond_etag_aspect
@serialize_person_aspect
def update_person(person, data):
person.update(data)
db.person.save(person)
return person

Perceba que, com a separação dos aspectos em funções distintas, o código ficou muito mais semântico:
  • retrive_person_aspect apenas recupera o documento do banco;
  • parse_data_aspect apenas faz o parsing dos dados recebidos;
  • respond_etag_aspect apenas gera o formato correto da resposta;
  • serialize_person_aspect apenas serializa o documento;
  • finalmente, update_person apenas atualiza o documento.

Observações

  • db é um objeto de banco de dados MongoDB, apenas para fim de exemplo.
  • app é uma aplicação Flask, apenas para fim de exemplo.
  • A ordem dos decoradores é importante.
  • Os imports foram omitidos:
import json
from functools import wraps
from hashlib import md5

Na parte II abordaremos mixins.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (ℭacilhας, ℒa ℬatalema) em 18 de April de 2015 às 21:05

RLock

Dando continuidade o artigo sobre thread, um recurso muito útil é lock reentrante.

Lock reentrante é uma variação de lock que pode ser realocado múltiplas vezes pelo mesmo thread e não pode ser liberado por outro thread. É muito útil em funções recursivas, mas funciona também para garantir que o lock seja alocado e liberado pelo mesmo thread.

A fábrica (factory) para criar locks reentrantes é threading.RLock.

É preciso tomar cuidado para que todos os threads compartilhem o mesmo lock, senão ele se torna inútil:
lock = RLock()

thr1 = Thread(target=func1, args=(lock, ))
thr2 = Thread(target=func2, args=(lock, ))
thr3 = Thread(target=func3, args=(lock, ))

Dentro da função, é preciso alocá-lo (acquire) no inicío e liberá-lo (release) ao final. Por exemplo:
def func1(lock):
lock.acquire()
try:
# executa o procedimento
...
finally:
lock.release()

Protegendo um objeto mutável

Uma utilidade para o lock reentrante é proteger métodos que alterem o conteúdo de um objeto.

Imagine que temos uma classe Person com dados, como identity_code (CPF) que podem sofrer alterações em threads diferentes (sei que não é uma boa abordagem, mas apenas como exemplo).

Podemos criar um decorador que torna um método thread-safe usando lock reentrante:
def lock(wrapped):
lock_ = RLock()

@wraps(wrapped)
def wrapper(*args, **kwargs):
with lock_:
return wrapped(*args, **kwargs)

return wrapper

Esse decorador pode ser usado nos setters de cada propriedade:
class Person(object):

...

@property
def identity_code(self):
return self.__identity_code

@identity_code.setter
@lock
def identity_code(self, value):
self.__identity_code = value

...

Na verdade essa abordagem não resolve 100% o problema, mas já reduz muito a ocorrência de bugs.

Protegendo qualquer objeto

Porém a abordagem acima apenas protege parcialmente o objeto e não funciona para classes de terceiros.

Outra abordagem é usar um lock para todo o objeto, tanto leitura quanto gravação, agnóstico a qual objeto está sendo protegido. Assim, não há necessidade de usarmos propriedades.

Vamos criar uma classe para trancar qualquer objeto:
class ObjectLocker(object):

def __init__(self, obj):
self.__obj = obj
self.__lock = RLock()

def __enter__(self):
self.__lock.acquire()
return self.__obj

def __exit__(self, etype, exc, traceback):
self.__lock.release()

No código a instância dessa classe será passada para os threads, que terá de usar with para acessar o objeto original.

Ao usar with, o objeto original será trancado para o thread atual e liberado ao final.

A passagem será:
locker = ObjectLocker(Person(...))
thr = Thread(target=func, args=(locker, ))

Dentro da(s) função(ões) func a instância de Person deve ser acessa da seguinta forma:
with locker as person:
name = person.name
person.identity_code = data['identity_code']

Espero que os exemplos tenham sido úteis.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (ℭacilhας, ℒa ℬatalema) em 18 de April de 2015 às 21:00