2o Hangout Empreendedorismo Python Brasil

O pessoal do grupo Python Brasil está começando a fazer hangouts semanais pra falar sobre Python e Empreendedorismo e hoje participei do 2o Hangout. Falei um pouco sobre minha experiência e tentei falar alguma coisa sobre a importância do programador também ser um empreendedor.

Tentei falar, porque eu não tinha planejado o que falaria, só rabisquei alguns tópicos no caderno, mas aqui no blog eu posso detalhar um pouco o que eu pensei e colocar uns links também.

Esqueci de citar um dos links principais que gostaria, que é o curso How to Start a Startup do Sam Altman, CEO do YCombinator

Vídeo da Apresentação:

 

Curso

Notícias

Links dos Projetos

Podcasts

Livros

Outros Links

Bônus

Só sai da rotina quem tem uma

Semana que vem faço 31 anos.
Sempre que estou perto do meu aniversário fico nostálgico e começo a fazer uma retrospectiva da minha vida e lembrei que quando eu tinha 20 anos eu odiava qualquer rotina.

A geração do bullshit

A minha geração passou a adolescência ouvindo um monte de bullshit sobre ela mesma. Que merece tudo, que não pode ser criticada, que é especial, que todo mundo pode ser nômade digital feliz trabalhando com o que quiser o tempo todo e de onde quiser e mais um monte de coisas que transformaram essa geração em uma tremenda quebra de promessas (como diz meu amigo @dpassarini)

 

Bob Esponja - Bullshit

Pra não ficar tão ruim pra esse lado, acho que a geração seguinte é um pouco pior que precisa de reunião de pais na faculdade!

A religião da juventude

Virou uma religião, cuja divindade é o Eu e o mote da sagrada escritura é Você pode o que você quiser é só querer muito, provavelmente tirado de algum filme da Xuxa com os Trapalhões. A única coisa que pode te atrapalhar no caminho são os invejosos, que como uma força demoníaca não concordam com você!

E eu?

 

Eu não era diferente dos outros, achava que era mas era igualzinho e é capaz que eu ainda seja…

Corolário: eu odiava rotinas. Achava que rotinas eram feitas pra quem tinha preguiça de pensar, que quem fazia sempre a mesma coisa era um rato numa rodinha, que pessoas especiais tinham horários especiais.

O problema de não ter rotina é que você não tem controle. Tem dificuldade de planejar seu trabalho, seus estudos e até mesmo suas ideias. Você procrastina mais e sempre que eu decidia sentar a bunda na cadeira e fazer alguma coisa sempre começava pelo planejamento. Quando acabava de planejar me dava por satisfeito, como se já tivesse feito alguma coisa e na verdade, não tinha feito absolutamente nada.

Esses problemas acabam criando uma ansiedade gigantesca e me deixavam doente de verdade: manchas na pele, labirintite, perda de audição e ataques de pânico. Até que travei, perdi a vontade de fazer tudo, já que não estava conseguindo fazer nada. Perdi praticamente um semestre inteiro da faculdade e essa paralisia destruiu tudo que eu achava que sabia sobre mim.

A recuperação

Aquela imagem que eu tinha de mim não servia pra mais nada. Não era especial, porra nenhuma, mal conseguia lidar com a ansiedade e as frustrações. Tive que aprender continuamente a ser humilde.

E o que humildade tem a ver com rotina? Pra mim tudo. Pra você construir uma rotina você precisa se forçar muitas vezes a fazer coisas que você não quer, em momentos que você não quer. Fazer coisas chatas sem pensar que você é bom demais pra aquilo. Tem que meter a mão na massa de fato. Reconhecer que pra chegar em algum lugar você tem que começar do zero.

 

Enfim, o assunto

A rotina é a melhor forma pra você alcançar algum objetivo e ela não precisa ser uma coisa maçante e inflexível. A rotina é só a sua maneira de fazer alguma coisa normalmente. Não precisa ser a minha rotina, nem a rotina do Abilio Diniz. A rotina só precisa de limites e metas impostas por você mesmo. Pode até ser uma coisa pequena como ligar pra 10 clientes por dia, responder 40 perguntas no MercadoLivre ou escrever uma página de um livro por dia.

Não precisa ser chato e entediante. Só não pode dar aquela roubadinha na rotina e deixar ela livre demais a ponto que você consiga dar desculpas pra si mesmo.

Nunca tinha parado pra pensar nisso até ontem. Eu tenho uma rotina mas nunca tinha atribuído a ela várias coisas que alcancei como aprender inglês sozinho, criar vários produtos, trabalhar em home office e muitas outras coisas que seriam impossíveis sem uma rotina.

Um livro que estou lendo me ajudou bastante a enxergar isso: The Willpower Instinct. Nesse livro a autora, que é professora de Stanford, mostra como a rotina, entre outras coisas, permite que você use melhor seu córtex pré-frontal, justamente a área do cérebro que é responsável pelo seu auto-controle.

A rotina não é a única forma de alcançar objetivos, tem gente que consegue criar as coisas de forma caótica. Mas isso funciona pra todo mundo? e pra você? Essa é uma boa pergunta pra se fazer antes de descartar a rotina, como o Fernandinho de 20 anos…

Arnold…. and his creepy smile

Saia da Rotina

Sempre ouvimos isso: “Saia da Rotina”, “Pense fora da caixa”, “Mude pra variar”, etc… para todas essas coisas se pressupõe que você tenha uma rotina. É uma delícia sair da rotina, justamente porque existe a rotina. Quem não gosta de tirar um dia na semana pra ir num barzinho com os amigos? Se o barzinho fosse todo dia o dia inteiro e você não trabalha em bar seria um problema e não uma coisa agradável. Todas essas coisas de sair da rotina e pensar fora da caixa são tão cliché, tão lugar comum e é isso o que mais vemos por aí, é a parte gostosa da semana e do tempo presente…mas pra ter a parte legal na qual você se visualiza no futuro é preciso justamente a rotina…

Celery com múltiplas filas, retry e tarefas agendadas

No ano passado eu escrevi um post sobre Tarefas demoradas de forma assíncrona com Django e Celery, que serve para a maioria dos casos de uso do celery. O problema é que você pode querer e fazer muito mais com o celery, como ter filas diferentes para tarefas prioritárias, executar um retry após a falha de uma tarefa ou agendar a tarefa para ser executada apenas em outro horário ou outro dia.

Retry em uma Tarefa

Suponhamos que isso seja uma caveira que sua tarefa depende de uma API externa, conexão com algum site ou algum outro motivo que possa levá-la a um ConnectionError, por exemplo.

É provável que dentro de alguns instantes a API, site, etc. esteja no ar e que se você executar sua tarefa novamente ela funcione. Para isso podemos agendar um retry para esta tarefa:


from celery import shared_task
 
@shared_task(bind=True, max_retries=3)
def acessar_sistema_horrivel(self, meu_objeto_id):
    from core.models import MeuObjeto
    from requests import ConnectionError
 
    objeto = MeuObjeto.objects.get(pk=meu_objeto_id)
 
    # Se tiver ConnectionError tenta de novo em 180 segundos
    try:
 
        objeto.acessar_sistema_horrivel()
  
    except ConnectionError as exc:
        self.retry(exc=exc, countdown=180)
 
 

Interessante que dentro de uma função você está usando self.retry. Isso é possível graças ao bind=True no decorator do shared_task, que faz com que nossa função acessar_sistema_horrivel seja na verdade um método da classe Task. Isso nos obriga a colocar self como primeiro argumento da função também.

O número máximo de tentativas para executar essa tarefa é o max_retries=3 definido no decorator

ETA – Agendando a tarefa para começar mais tarde

Agora o cenário é o seguinte, seu sistema vai chamar uma tarefa assíncrona, mais quer que ela seja executada apenas daqui a uma hora.

Para isso podemos chamar a task setando a propriedade ETA (estimated time of arrival) e isso significa que sua tarefa só será executada depois daquele horário (não necessariamente para começar aquele horário, isso vai depender se você possui workers disponíveis, para agendar exatamente como no cron você pode usar o CeleryBeat) .

 


from django.utils import timezone

agora = timezone.now() 
 
# Depois é daqui a uma hora 
#(usei o replace pq quis mostrar, mas vc poderia usar o timedelta para somar também)
depois = agora.replace(hour=agora.hour + 1)
 
acessar_sistema_horrivel.apply_async((meu_objeto_id), eta=depois)
 

Colocando mais de uma fila de execução

Quando você executa o celery ele cria uma fila no seu broker (no caso do post anterior, era o RabbitMQ). A fila padrão chama celery. Qual a implicação? Se você possui várias tarefas assíncronas a serem executadas ficam todas na mesma fila, das qual os workers vão pegar as mensagens e executar.

Imagine que temos além da task acessar_sistema_horrivel, uma outra task chamada tarefa_demorada.

Então dado o seguinte cenário:

3 tarefas: uma lenta e uma mais rápida e a acessar_sistema_horrivel
1 fila
4 workers

E imagine que o sistema produziu 10 requisições da tarefa_demorada para serem executadas e em seguida produziu mais 10 da outra tarefa. O que vai acontecer? Seus workers ficarão todos ocupados buscando executando as requisições de tarefa_demorada que entraram primeiro e nenhum estará trabalhando na tarefa mais rápida.

A solução para isso é produzir filas diferenciadas para as tarefas prioritárias.


# CELERY ROUTES
CELERY_ROUTES = {
    'core.tasks.acessar_sistema_horrivel': {'queue': 'fila_horrivel'},
    'core.tasks.tarefa_demorada': {'queue': 'fila_demorada'},
    'core.tasks.tarefa_mais_rapida': {'queue': 'fila_rapida'},
}

Isso é suficiente para que as mensagens para essas tarefas sejam enviadas para essas filas do RabbitMQ. Detalhe, essas filas são criadas de forma permanente no RabbitMQ, mas isso também pode ser configurado.

Agora para rodar os consumidores para essas filas quando formos executar o celery podemos definir com o parâmetro -Q. No caso fica assim:


celery --app=nome_projeto worker -Q fila_horrivel,fila_demorada,fila_rapida --autoscale=10,5

Estamos iniciando os workers para todas essas filas. Neste caso estou colocando também o parâmetro autoscale, indicando para trabalhar com no mínimo 5 workers e caso haja muitas tarefas o celery adiciona mais workers até o máximo de 10. Isso é bom para economizar recursos do seu sistema, caso você tenha horários com mais produção de tarefas.

Como mostramos no outro post, para usar isto sob o supervisord, você pode modificar aquele mesmo script


[program:celery]
command=/home/deploy/.virtualenvs/meu_virtual_env/bin/celery --app=nome_projeto worker -Q fila_horrivel,fila_demorada,fila_rapida --autoscale=10,5
directory=/home/deploy/webapps/projeto_django
user=nobody
autostart=true
autorestart=true
redirect_stderr=true

Em seguida rodar o reread e o update, porque o arquivo de configuração mudou e reiniciar o supervisord para esse arquivo.


sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart gunicorn

Com isso seus workers vão executar tarefas de cada uma das filas, não travando os workers para só um tipo de tarefa. Há diversas outras formas de colocar seus workers para funcionar.

Chamando Tarefas Sequenciais

Outro problema comum, é precisar chamar duas tarefas assíncronas , uma depois da outra. Isso pode acontecer em diversos cenários, ex: o caso de a segunda tarefa receber como parâmetro o resultado da primeira, ou da primeira tarefa salvar algum dado e a segunda tarefa trabalhar aquele dado, etc…

Para isso nós podemos usar o Chain, que é o recomendado ao invés de chamar a segunda tarefa assíncrona com o delay dentro da primeira tarefa.


from celery import chain
from tasks import salvar_dados, trabalhar_dados
 
# Estamos chamando o método s das tasks, que as usa como subtasks de uma task gerada pelo chain.
chain(salvar_dados.s(meu_objeto_id) | trabalhar_dados.s())

A tarefa trabalhar_dados vai utilizar o return ou resultado da tarefa salvar_dados como parâmetro.
O chain em sí está gerando uma task, então para ele também serve chamar o apply_async com um eta definido, por exemplo:


chain(salvar_dados.s(meu_objeto_id) | trabalhar_dados.s()).apply_async(eta=depois)

Ignorando os resultados do ResultBackend

Se você só usa as tasks para executar alguma coisa que não precisa do return da task, você pode ignorar o ResultBackend e ter um ganho de performance.

A maioria dos casos não precisa guardar o resultado do return, então é só uma dica interessante se você já está salvando algo nos models, ou fazendo whatever diretamente dentro da sua task, coloque isso no seu settings.py:


CELERY_IGNORE_RESULT = True

 

Na verdade tem muito mais coisas legais no Celery, que ficarão pra um próximo post.

Fontes

http://docs.celeryproject.org/en/latest/userguide/tasks.html

http://docs.celeryproject.org/en/latest/userguide/optimizing.html#guide-optimizing

https://denibertovic.com/posts/celery-best-practices/

https://news.ycombinator.com/item?id=7909201

http://docs.celeryproject.org/en/latest/userguide/workers.html

http://docs.celeryproject.org/en/latest/userguide/canvas.html

 

Super Bônus

Celery Messaging at Scale at Instagram – Apresentação Pycon 2013

De esgotado a empolgado. O que deu certo aceitando um desafio em 2015

“Não será fácil. Mas você já fez coisas difíceis antes.” *

Depois de 10 semanas no vale do silício conversando com investidores, programadores e empreendedores de tecnologia, percebi que o produto que tinha me dedicado por mais de um ano não fazia mais sentido pra mim.

eeeee. nope!

 

Comecei 2015 exausto. Depois de vários anos empreendendo estava me perguntando se era hora de prestar um concurso público ou trabalhar “na minha”.

Pensei em desistir de empreender, pensei em como é difícil tirar algo do papel e sabia que se quisesse empreender teria que passar por várias etapas pelas quais já tinha passado algumas vezes nos últimos anos. Mas as vezes não adianta querer fugir, e o que foi uma simples conversa informal que tive com o Dr Antônio Maia no EC14 acabou se transformando num convite para ser sócio de uma empresa com ideias bastante ambiciosas para transformar a área jurídica no Brasil. As ideias eram excitantes e boas demais para serem preteridas e resolvi então abraçar mais um desafio como CTO de uma empresa de Legal Tech.

Studying law. making a responsible choice for my future

Quem já foi CTO no início de uma startup sabe como é difícil você dar os primeiros passos. Estudar as necessidades de um mercado que não é o seu, planejar as estruturas, começar a escrever o código e o principal e mais difícil: Montar um time de excelência.

Não tem todo mundo, mas tem bastante gente

Não tem todo mundo, mas tem bastante gente

Existe um provérbio grego que diz que O início é metade de qualquer ação. Acho essa metáfora linda, pois não é pra tanto, mas mesmo assim começamos do zero na última semana de fevereiro/15 com uma única posição dentro de um escritório de advocacia e estamos terminando o ano com um conjunto inteiro na Av. Paulista, um time lindo de desenvolvimento, um stande e  apresentação na maior feira da nossa área, com um produto lançado, o LegalNote, crescendo rapidamente com mais de mil usuários cadastrados e milhares de processos e com o nosso outro produto o Diligeiro correndo na fase final de desenvolvimento.

Trabalhamos até a véspera da véspera de ano novo, empolgados por todas essas conquistas que não foram fáceis e eu tenho a certeza de que daqui pra frente tudo continuará sendo difícil, mas nós podemos olhar pra trás e ver que já fizemos coisas difíceis antes.

Muito obrigado à todos! Um excelente 2016!

Um obrigado especial a todos que trabalham duro comigo:

Chuckeeey
Daniel , o mago das regex
Derek Oedenkoven
Dr Antonio Maia
Dr Fabio Abrahao
Gui AMS
Marcus Beckenkamp
Vitão Jar Jar
Gustavo UX
Rafael, o lendário!
Muller #Zueiro
* Li essa frase em algum lugar essa semana e achei fantástica.

E quando uma empresa gigante resolve virar sua concorrente?

Você cria um produto, vira pioneiro em uma área, corre todos os riscos e fica cheio de incertezas, tanto suas, quanto dos clientes confrontados com “A novidade.”

Imagine que nesse cenário, um pequeno grupo abraça aquilo que você fez, ama o seu projeto e você conseguiu criar algo dentro de uma comunidade.

De repente, o gigante acordou, imagine um gigante mesmo, a própria Apple. E ela aprova sua ideia. Aprova tanto que resolve criar uma versão própria do seu produto.

Agora a Apple é sua concorrente!

Steve Jobs - Doctor Evil

E aí, senta e chora?


Isso aqui não é uma anedota, é um caso verídico.

Os criadores do smartwatch Pebble já passaram por vários perrengues, foram acelerados pela YCombinator, o projeto não foi pra frente, não conseguiram levantar capital porque eram uma empresa de Hardware, depois concluíram com sucesso uma campanha no kickstarter e por fim foram lançando e evoluindo o Pebble, tudo a partir da ideia do Eric Migicovsky de criar um display de relógio que mostrasse as notificações do celular.

Bom, imagine a cabeça desse cara quando o Google resolveu lançar o próprio smartwatch e quando a Apple resolveu lançar o Apple Watch.

Agora imagina como ele se sente, vendo que um concorrente desse tamanho, um gigante, está mais abrindo mercado para eles do que prejudicando.

E pode ser que um dia o Pebble se torne tão grande e vire realmente um competidor do Apple Watch. Quem sabe…

 

Por quê estou falando tudo isso?

Porque com o lançamento do Apple Watch muita gente que não tinha ideia do que era um SmartWatch acabou descobrindo o que é isso e, independente de descobrir através da Apple, puderam também se interessar e ir atrás de outros modelos, conhecendo o Pebble, que Dobrou suas vendas!

Veja: Aparentemente Apple Watch ajudou a DOBRAR as vendas do Pebble

 

Me inspirei pra escrever no post do Diogo Novaes no facebook. Aliás, um cara que vale muito a pena seguir.

Tarefas demoradas de forma assíncrona com Django e Celery

Estou escrevendo esse post empolgado por uma lightning talk que fiz no GruPy-SP (16/07). Assim aproveito pra explicar um pouco mais o que estou dizendo nos slides.

O problema de tarefas demoradas do lado do servidor

Sempre que o cliente faz uma requisição web (request), o servidor faz um processamento, normalmente pra quem usa o django, ele lê a requisição, trata os dados recebidos, salva ou recupera registros do banco de dados (através dos models), faz algum processamento do que será exibido para o usuário, renderiza isso em um template e manda uma resposta (response) para o cliente.

Dependendo da tarefa que você executa no servidor a resposta pode demorar muito e isso leva à problemas de TimeOut, a experiência do usuário fica comprometida (quanto mais o servidor demorar pra responder maior a chance do usuário sair do seu site) e também pode acontecer da lentidão ser causada por outros, como por exemplo o uso de uma API externa.

Existem diversas tarefas que podem demorar pra ser executadas. Se você tiver que criar um relatório pesado, acionado por um client web. Se de repente você precisar enviar diferentes emails para uma lista ou por exemplo editar um vídeo depois que o usuário faz o upload na sua página.

Caso real

Esse é um problema que me deparei um dia na geração de um relatório. O relatório levava cerca de 20 minutos para ser gerado, o cliente recebia um erro de timeout e obviamente não dá pra esperar 20 minutos pra gerar alguma coisa. Pra driblar isso e deixar a tarefa em background, alguém resolveu usar um comando do sistema operacional. (No linux se você colocar & no final de um comando esse comando roda em background).

django-view-os-system

Note que em seguida o django envia mostra uma mensagem ao usuário de que ele será avisado por e-mail ao final da geração do relatório.
Alguma coisa não parece certa aqui.

Me arrependo imediatamente dessa decisão

Celery – A solução para esses problemas!

O Celery é um gerenciador de tarefas assíncronas. Com ele você pode executar uma fila de tarefas (que ele recebe por meio de mensagens), pode agendar tarefas direto no seu projeto sem precisar do cron e ele ainda tem integração fácil com a maioria dos frameworks python mais utilizados (django, flask, tornado, etc.)

Como o Celery funciona

Essa imagem kibada da internet dá uma visão geral de como fica o fluxo da sua aplicação.

estrutura-celery

  • O User (ou Client ou Producer) é a sua aplicação Django.
  • O AMPQ Broker é um Message Broker. Um programa responsável por manter a fila de mensagens que serão trocadas entre o seu programa e o Celery, geralmente é o RabbitMQ ou o Redis
  • Os workers (ou consumers) que vão executar as tarefas que você quer que sejam assíncronas.
  • O Result Store, que é onde os workers podem ou não salvar os resultados das tarefas que foram executadas.

O Client pode passar uma tarefa, uma lista de tarefas, tarefas periódicas ou o retry de alguma tarefa pra fila do Message Broker. O Message Broker distribui essas tarefas entre os workers e o resultado dessas tarefas pode ser escrito em um Result Store (Memcahed, RDBMS, MongoDB, etc…) que mais tarde pode ser lido pelo Client novamente.

Qual Broker utilizar?

O recomendado pelo Celery é o RabbitMQ.

Instalando e configurando o RabbitMQ

Existem vários exemplos de como utilizar o Redis, eu vou mostrar como usar o RabbitMQ.

Você só precisa:

  1. Instalar o RabbitMQ (Baixar o pacote no site ou adicionar o repo deles no sources.list e instalar com APT-GET)
    sudo apt-get install rabbitmq-server
  2. Criar um usuário, um virtual host e dar permissões para esse usuário no virtualhost:
    
    sudo rabbitmqctl add_user myuser mypassword
    sudo rabbitmqctl add_vhost myvhost
    sudo rabbitmqctl set_permissions -p myvhost myuser ".*" ".*" ".*"
    

Instalando e configurando o Celery

pip install celery

No seu settings.py:

#Celery Config
BROKER_URL = 'amqp://guest:[email protected]:5672//'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

Na pasta do projeto (a mesma pasta do settings.py) crie um arquivo chamado celery.py:


from __future__ import absolute_import

import os
from celery import Celery
from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nome_do_proj.settings')

app = Celery('nome_do_proj')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Esse autodiscover_tasks permite que seu projeto ache todas as tarefas assíncronas de cada app instalada nele. Nessa mesma pasta do settings.py, você vai modificar o arquivo de pacote __init__.py:


from __future__ import absolute_import

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

Criando as tarefas assíncronas do seu app

Na pasta do seu app crie um arquivo chamado tasks.py:

from __future__ import absolute_import
from celery import shared_task
from relatorios import gerar_relatorio_excel


@shared_task
def gerar_relatorio(data_inicial, data_final, email):
    gerar_relatorio_excel(
        data_inicial = data_inicial,
        data_final = data_final,
        email = email
    )
    return "Relatorio Excel gerado"

Agora é só fazer importar essa função que foi criada usando o método delay que foi adicionado à sua função pelo decorator shared_task.

tabelao assincrono

Rodando o Celery

Agora você precisa rodar o celery. Ele vai rodar os seus workers pra executar suas tarefas de forma assíncrona. Por padrão ele inicia um worker para cada núcleo de processador, mas você pode determinar quantos com -c Numero_de_workers

celery --app=nome_projeto worker --loglevel=INFO

E então você verá essa tela:

celery-rodando

Você pode então testar sua função assíncrona com o shell do django mesmo:

chama funcao

E o que aparece na tela que está mostrando o celery:

aparece no celery

Colocando o Celery em Produção

Para usar o Celery em produção eu recomendo que você use o Supervisor

Para instalar o supervisor:

sudo apt-get install supervisor

Depois crie um arquivo de configuração para o celery e coloque um link simbólico para esse arquivo no /etc/supervisor/conf.d/

[program:celery]
command=/home/deploy/.virtualenvs/meu_virtual_env/bin/celery --app=nome_proj worker --loglevel=INFO
directory=/home/deploy/webapps/projeto_django
user=nobody
autostart=true
autorestart=true
redirect_stderr=true

Para o supervisor ler novamente os arquivos que estão em sua pasta de configuração:

sudo supervisorctl reread
sudo supervisorctl update

Agora é só iniciar o celery:

sudo supervisorctl start celery

Bom, acho que é só isso. Esses são os slides da minha apresentação:

Continuação

Celery com múltiplas filas, retry e tarefas agendadas

Fontes

E aqui vão as fontes de pesquisa (ou algumas) que eu utilizei nesse processo:

Bônus:

Como o Feed do Instagram usa o Celery e o RabbitMQ

Um pequeno prazer de uma startup que não deu certo.

 

Quem nunca teve uma empresa que não deu certo, que atire a primeira pedra.

Sempre gostei de empreendedorismo. Eu gostava de ler matérias sobre empresas, gostava de ir nas empresas dos meus pais e gostava dos filmes dos anos 80 estilo Jerry Maguire. Minha família sempre foi empreendedora. Meu pai teve de loja de material de aquarismo até distribuidora de salgadinho de bar, meu tio construiu a maior rede de salões de beleza da zona norte e até hoje não se passa uma semana sem que minha mãe me fale uma ideia nova que ela teve (Se eu publicar alguma, ela me mata). O fato é que o empreendedorismo está no meu sangue.

No final de 2011, eu e meu amigo Daniel resolvemos montar uma startup. Na ocasião eu tinha um site que revendia instrumentos musicais. Nada muito formal, mas era uma escola pra mim. Estava ganhando dinheiro, me mantendo, tive a oportunidade de largar um emprego público e fazer mais dinheiro em casa de cueca do que indo perfumado até o prédio da FEA. Falar sobre a Apoio Musical levaria até mais de um post sobre os 2 anos que eu a mantive no ar e ela me manteve.

Bom, montamos essa startup porque estávamos vidrados em Crowdsourcing. Queríamos muito, que o crowdsourcing fosse um jeito de dar às empresas a oportunidade de gastar pouco pra ter ideias de qualidade e de dar às pessoas a oportunidade de trabalhar em projetos de grandes empresa, mostrando seu potencial.

 

O primeiro problema que enfrentaríamos era o do ovo e o da galinha: como teríamos empresas sem ter pessoas interessadas em anunciar e como teríamos pessoas pra participar dos desafios sem ter empresas com desafios?

Enfim, resolvemos começar buscando às pessoas. (O que hoje eu acredito que não foi a melhor estratégia).

Pra alcançar essas pessoas nós resolvemos criar um Desafio com Ideias que pudessem melhorar a cidade de São Paulo. Chamamos isso de Desafio São Paulo.

Criamos um aplicativo para o facebook pra poder receber as ideias, já que ainda não tínhamos uma plataforma criada e não me lembro como alguém gostou do desafio e ele foi parar no Catraca Livre.

ideias-na-mesa-catraca-livre

Isso foi o suficiente pra várias pessoas entrarem no Desafio. Nisso tivemos um outro problema: Como escolher qual ideia é a melhor? E nisso, a CAOS Focado que é uma empresa de consultoria nos ajudou criando um método objetivo pra definir quais eram as melhores ideias (eu deveria ter filmado pra mostrar quão genial foi o Miguel Chaves resolvendo isso pra gente).

A startup como você já previu no começo do texto, escafedeu-se, fizemos o desafio, não conseguimos fechar com nenhuma outra empresa um desafio sequer, apesar de negociar durante meses com uma empresa grande da área de turismo. Então o que eu estou comemorando aqui como um pequeno prazer? Olhe as ideias escolhidas como as melhores para São Paulo no nosso desafio e pense no que mudou em São Paulo de 2012 para 2015.

  • Ciclo Faixas com acesso a CPTM nas marginais
  • Menos vagas de rua para carros
  • Ruas de lazer aos domingos
  • Transporte Coletivo 24 horas
  • WiFi gratuito em locais públicos

Isso tudo começou a mudar em São Paulo e vai continuar mudando porque agora já é tendência. Se quiser ter certeza, confere meu post original de quando eu publiquei o desafio em março de 2012:

 

http://blog.ideiasnamesa.com.br/desfile-das-campeas-desafio-sao-paulo/

*args e **kwargs não são coisas mágicas em Python

* é um operador e não é só de multiplicação. Hun!?

Muita gente acha que *args e **kwargs são coisas mágicas em Python.

* é um operador que transforma listas em argumentos de uma função.

Por exemplo, imagina que você quer usar a função replace em uma string. Essa função recebe 2 argumentos, o primeiro para o valor que precisa ser substituído e o segundo para o novo valor.

>>> 'a escambau'.replace('a ', 'o ')
>>> 'o escambau'
>>> # Agora tentando passar os parâmetros com uma lista
>>>
>>> args = ['a ','o ']
>>> 'a escambau'.replace(args)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: replace() takes at least 2 arguments (1 given)
>>> 
>>> #Para que isso funcione basta usar o operador *
>>> 'a escambau'.replace(*args)
'o escambau'


Super simples.

O ** segue a mesma lógica, é um operador que transforma um dicionário em keyword arguments de uma função.

Vou criar uma função que recebe dois argumentos e printa o nome com a idade (como na revista caras)

>>> d = {'nome' : 'Fernando', 'idade': 29}
>>> def caras_me(nome,idade):
...     print("%s(%s)" % (nome,idade))
... 
>>> #Colocando só o dicionário sem o operador:
>>> caras_me(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: caras_me() takes exactly 2 arguments (1 given)
>>> # Colocando o dicionário usando o operador **
>>> caras_me(**d)
Fernando(29)

Você pode dar uma olhada na documentação oficial, caso queira:

https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists

Usando Regex para fazer split para mais de um valor

Precisei fazer split em alguns textos jurídicos e como na língua portuguesa os adjetivos sofrem flexão de gênero , tive que separar um texto por mais de um valor.

A sorte é que o módulo re de regex do python é excelente e vem com essa função split, você só precisa passar o pattern e o texto. No caso eu usei ‘Advogado|Advogada ‘, lembrando que o |(pipe) é um “ou” em expressões regulares.

Como criar um instalador MSI utilizando o Inno Setup

Essa é a terceira parte da série de Posts Distribuir Programas em Python para Desktops Windows. Nela você vai aprender como criar um instalador MSI utilizando o Inno Setup e colocando as DLLs do MSVCR para o Python funcionar em qualquer máquina windows.

As outras duas partes são:

Bom, nós vimos como criar um instalador MSI com o cx_freeze e utilizando as DLL’s de MSVCR da própria página no primeiro post, depois vimos como modificar o programa para ele ter um Auto-Update. Só que quando alteramos o setup.py pra gerar o programa com o Auto-Update não conseguimos mais fazer um instalador com o cx_freeze. Isso acontece porque o Esky modifica o seu programa, ele cria um executável que verifica se há algum download disponível no FTP, se tiver ele faz o download, faz o update, verifica se deu certo e exclui as bibliotecas antigas.

Primeira coisa: baixar e instalar o Inno Setup.

O Inno Setup cria um arquivo .iss que nada mais é que um script para criar o seu instalador. Abrindo o Inno você tem a opção de escrever esse script diretamente ou usar o Script Wizard (Um assistente):

inno

 

Nós vamos criar um instalador usando o assistente, primeiro nós vamos utilizar aquele arquivo que geramos no post anterior, o boneca-1.0.1.win32.zip. Você precisa ter descompactado esse arquivo:

boneca-esky-conteudo

No Inno Setup clique em File >> New. Você abrirá o Assistente, ele é fácil de usar, preencha esses dados como quiser:

assistente-inno-setup-1

Na próxima tela você pode escolher onde o Instalador vai colocar o seu programa. O Default é o Program Files folder, mas tem um porém: Se o seu código não tiver Assinatura Digital (Code Signing) você vai ter dificuldades com o UAC do Windows, porque ele não vai conferir a autenticidade do seu código e isso implicará em problemas com antivírus, em bloqueio do programa pelo windows e principalmente ele pode impedir que o programa faça o auto-update, por isso use uma outra pasta a princípio. Você pode escrever um caminho ou usar uma Constante das pastas do Windows do próprio Inno Setup. [Recomendável]

assistente-inno-setup-2

Na terceira tela você vai colocar quais os programas, pastas e arquivos serão instalados pelo instalador, no caso o boneca.exe e o python27.dll ficaram na raiz e também a pasta boneca-1.0.1.win32 com o conteúdo dela.

Então coloque boneca.exe no campo de Application main executable file
Em seguida, clique em Add File para colocar o python27.dll e depois em Add Folder para adicionar a pasta boneca-1.0.1.win32:

assistente-inno-setup-3

Agora é só seguir em diante no assistente, no final ele vai criar o arquivo .iss. Você já pode compilar o arquivo e ele vai gerar o instalador .msi mas está faltando agora adicionar as DLLs do MSVCR. Então baixe de acordo com a sua versão do python:

Agora você precisa modificar o código do seu arquivo .iss pra ele instalar as DLLs junto com o seu programa. Isso aqui eu usei essa solução que achei no StackOverFlow e ela funciona muito bem:

Na seção Files coloque o caminho do vc_redist que você baixou:

[Files]
Source: "vcredist_x86.exe"; DestDir: {tmp}; Flags: deleteafterinstall

No final da seção Run adicione esse código:

[Run]
; add the Parameters, WorkingDir and StatusMsg as you wish, just keep here
; the conditional installation Check
Filename: "{tmp}\vcredist_x86.exe"; Check: VCRedistNeedsInstall

[Code]
#IFDEF UNICODE
 #DEFINE AW "W"
#ELSE
 #DEFINE AW "A"
#ENDIF
type
 INSTALLSTATE = Longint;
const
 INSTALLSTATE_INVALIDARG = -2; // An invalid parameter was passed to the function.
 INSTALLSTATE_UNKNOWN = -1; // The product is neither advertised or installed.
 INSTALLSTATE_ADVERTISED = 1; // The product is advertised but not installed.
 INSTALLSTATE_ABSENT = 2; // The product is installed for a different user.
 INSTALLSTATE_DEFAULT = 5; // The product is installed for the current user.

 VC_2005_REDIST_X86 = '{A49F249F-0C91-497F-86DF-B2585E8E76B7}';
 VC_2005_REDIST_X64 = '{6E8E85E8-CE4B-4FF5-91F7-04999C9FAE6A}';
 VC_2005_REDIST_IA64 = '{03ED71EA-F531-4927-AABD-1C31BCE8E187}';
 VC_2005_SP1_REDIST_X86 = '{7299052B-02A4-4627-81F2-1818DA5D550D}';
 VC_2005_SP1_REDIST_X64 = '{071C9B48-7C32-4621-A0AC-3F809523288F}';
 VC_2005_SP1_REDIST_IA64 = '{0F8FB34E-675E-42ED-850B-29D98C2ECE08}';
 VC_2005_SP1_ATL_SEC_UPD_REDIST_X86 = '{837B34E3-7C30-493C-8F6A-2B0F04E2912C}';
 VC_2005_SP1_ATL_SEC_UPD_REDIST_X64 = '{6CE5BAE9-D3CA-4B99-891A-1DC6C118A5FC}';
 VC_2005_SP1_ATL_SEC_UPD_REDIST_IA64 = '{85025851-A784-46D8-950D-05CB3CA43A13}';

 VC_2008_REDIST_X86 = '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}';
 VC_2008_REDIST_X64 = '{350AA351-21FA-3270-8B7A-835434E766AD}';
 VC_2008_REDIST_IA64 = '{2B547B43-DB50-3139-9EBE-37D419E0F5FA}';
 VC_2008_SP1_REDIST_X86 = '{9A25302D-30C0-39D9-BD6F-21E6EC160475}';
 VC_2008_SP1_REDIST_X64 = '{8220EEFE-38CD-377E-8595-13398D740ACE}';
 VC_2008_SP1_REDIST_IA64 = '{5827ECE1-AEB0-328E-B813-6FC68622C1F9}';
 VC_2008_SP1_ATL_SEC_UPD_REDIST_X86 = '{1F1C2DFC-2D24-3E06-BCB8-725134ADF989}';
 VC_2008_SP1_ATL_SEC_UPD_REDIST_X64 = '{4B6C7001-C7D6-3710-913E-5BC23FCE91E6}';
 VC_2008_SP1_ATL_SEC_UPD_REDIST_IA64 = '{977AD349-C2A8-39DD-9273-285C08987C7B}';
 VC_2008_SP1_MFC_SEC_UPD_REDIST_X86 = '{9BE518E6-ECC6-35A9-88E4-87755C07200F}';
 VC_2008_SP1_MFC_SEC_UPD_REDIST_X64 = '{5FCE6D76-F5DC-37AB-B2B8-22AB8CEDB1D4}';
 VC_2008_SP1_MFC_SEC_UPD_REDIST_IA64 = '{515643D1-4E9E-342F-A75A-D1F16448DC04}';

 VC_2010_REDIST_X86 = '{196BB40D-1578-3D01-B289-BEFC77A11A1E}';
 VC_2010_REDIST_X64 = '{DA5E371C-6333-3D8A-93A4-6FD5B20BCC6E}';
 VC_2010_REDIST_IA64 = '{C1A35166-4301-38E9-BA67-02823AD72A1B}';
 VC_2010_SP1_REDIST_X86 = '{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}';
 VC_2010_SP1_REDIST_X64 = '{1D8E6291-B0D5-35EC-8441-6616F567A0F7}';
 VC_2010_SP1_REDIST_IA64 = '{88C73C1C-2DE5-3B01-AFB8-B46EF4AB41CD}';

 // Microsoft Visual C++ 2012 x86 Minimum Runtime - 11.0.61030.0 (Update 4) 
 VC_2012_REDIST_MIN_UPD4_X86 = '{BD95A8CD-1D9F-35AD-981A-3E7925026EBB}';
 VC_2012_REDIST_MIN_UPD4_X64 = '{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}';
 // Microsoft Visual C++ 2012 x86 Additional Runtime - 11.0.61030.0 (Update 4) 
 VC_2012_REDIST_ADD_UPD4_X86 = '{B175520C-86A2-35A7-8619-86DC379688B9}';
 VC_2012_REDIST_ADD_UPD4_X64 = '{37B8F9C7-03FB-3253-8781-2517C99D7C00}';

function MsiQueryProductState(szProduct: string): INSTALLSTATE; 
 external [email protected] stdcall';

function VCVersionInstalled(const ProductID: string): Boolean;
begin
 Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

function VCRedistNeedsInstall: Boolean;
begin
 // here the Result must be True when you need to install your VCRedist
 // or False when you don't need to, so now it's upon you how you build
 // this statement, the following won't install your VC redist only when
 // the Visual C++ 2010 Redist (x86) and Visual C++ 2010 SP1 Redist(x86)
 // are installed for the current user
 Result := not (VCVersionInstalled(VC_2010_REDIST_X86) and 
 VCVersionInstalled(VC_2010_SP1_REDIST_X86));
end;


Agora salve e compile seu arquivo. Você terá um arquivo setup.exe como saída na pasta Output (ou o nome que você colocou) e ele vai instalar o seu programa da boneca com as DLLs necessárias pra rodar em qualquer Windows.

Conclusão:

Se você acompanhou os 3 posts você conseguiu criar um programa em python com auto-update e distribuí-lo para qualquer computador windows.

Observações Final sobre Code Signing:

Fiz uma pesquisa sobre code signing no ano passado(2014) , pode ser interessante para alguém:

Autoridade Certificadora Link Preço / ano
Global Sign https://www.globalsign.com/code-signing/ 229 usd
Thawte http://www.thawte.com/code-signing/index.html?tid=a_box_buycs 299 usd
Symantec Verisign http://www.symantec.com/code-signing 499 usd
Godaddy Code Signing http://br.godaddy.com/ssl/code-signing-certificate.aspx 479,99 reais / 199.99 usd
Ksoftware (Comodo partner) http://codesigning.ksoftware.net/ 95 usd
Digicert http://www.digicert.com/code-signing/ev-code-signing-compared.htm 223 usd
Obs:
Comparativo interessante: https://www.sslshopper.com/cheap-code-signing-certificates.html