Desabilitar webcam interna do notebook no Linux

Você pagou por todo o seu hardware, certo? Por que alguém quereria desabilitar a webcam interna ou qualquer outra coisa que veio com seu notebook? Bem, comprei uma webcam bem melhor que a do meu notebook. É uma Insta360 Link. É uma câmera 4k, com zoom ótico e controles por gestos usando inteligência artificial. Ela é muito, mas muito, muito melhor que a câmera interna do meu computador. E funcionou perfeitamente aqui no Linux.

Acontece que a webcam interna continua disponível. Isso poderia ser algo bom, certo? Bem, não exatamente… Às vezes, sem nenhum motivo, vou entrar numa reunião via Zoom ou Google Meet e a webcam interna é selecionada automaticamente. Então, ao invés dessa imagem:

Quem está na chamada acaba vendo isso:

Além do óbvio problema na qualidade da imagem, essa câmera ainda me pega de surpresa porque o notebook fica ao lado do meu monitor, então fica esse enquadramento acidental que você está vendo aí. É por isso que eu resolvi desabilitar a webcam interna.

Como descobrir o identificador da câmera

O primeiro passo para fazer isso é descobrir qual é o identificador do fabricante e do produto da minha câmera. Para isso, usei comando lsusb no terminal, que me deu essa saída:

Mas, peraí, porque lsusb? Sim, é estranho, mas a câmera interna, no meu e em vários outros modelos de notebook, é um dispositivo USB. Está ligada, por dentro, a uma interface USB da placa mãe. Vai entender…

Na segunda linha da saída acima, você pode ver a webcam interna listada, com o nome “Silicon Motion Web Camera”. E logo antes do nome, o identificador do produto: 2232:1080. Todos os dispositivos USB seguem esse padrão, os quatro primeiros dígitos são a identificação do fabricante, os quatro últimos são a identificação do produto.

Como desabilitar a webcam

Com esse código, no diretório /etc/udev/rules.d/ você vai criar um arquivo com uma regra para desabilitar a webcam interna. O nome deve começar com um número, que define a ordem de execução, e terminar com a extensão .rules. No meu caso, eu usei o nome 80-generic-webcam-remove.rules.

Se você não sabe como criar um arquivo no diretório /etc/, pode abrir um editor com o comando:

sudo nano /etc/udev/rules.d/80-generic-webcam-remove.rules

O conteúdo, no meu caso, ficou assim:

# ID 2232:1080 Generic Web Camera should be disabled
ACTION=="add", ATTR{idVendor}=="2232", ATTR{idProduct}=="1080", RUN="/bin/sh -c 'echo 1 >/sys/\$devpath/remove'"

Claro, substitua os números 2232 e 1080 no código acima pelos da sua webcam.

Salve e feche o editor. Se estiver usando nano, pressione CTRL+X, seguido de Y e Enter.

Reinicie seu computador e pronto, isso vai desabilitar a webcam interna em seu notebook.

Telegram Bloqueado no Brasil: o que exatamente aconteceu

Porque estamos com o aplicativo de mensagens Telegram bloqueado no Brasil? O tema foi noticiado amplamente por sites da área, como o Techtudo e a Revista Exame. Li várias matérias sobre o tema e fiquei incomodado com a falta de informações técnicas básicas. A maioria deles deixa a entender que o bloqueio é culpa do próprio Telegram, por não colaborar com a justiça. O Techtudo, por exemplo, publicou:

Não há previsão de retorno de funcionamento do Telegram. Isso ocorre porque é preciso, primeiro, que o aplicativo colabore com os órgãos federais para, então, ter ordem emitida desfazendo a sua suspensão.

O que exatamente aconteceu? A Polícia Federal obteve acesso a grupos neonazistas no Telegram que estariam recrutando menores para atos terroristas e, como parte das investigações, a justiça solicitou ao Telegram os números de telefones e outros dados de participantes de dois desses grupos. O Telegram demorou a responder e, quando respondeu, não entregou os dados e recorreu da decisão.

A sequência de eventos que levou ao Telegram bloqueado

Segundo o G1, o primeiro pedido da justiça para obter dados desses grupo aconteceu no dia 19/04, mas só foi encaminhada ao Telegram no dia 20/04, às 13h46. Um desses grupos já havia sido excluído há meses. O Telegram responde solicitando informações adicionais. A justiça envia parte dessas informações às 16h14 e o restante no dia seguinte, 21, às 8h06, momento em que o segundo grupo já havia sido também deletado. É parte da política de privacidade do Telegram a exclusão física real de dados que você mandou excluir. Embora a política de privacidade não fale sobre a exclusão de grupos, para as outras coisas todas, incluindo sua própria conta, o Telegram é claro: excluiu, já era, não temos cópia. Podemos deduzir que o mesmo se aplica também a grupos.

Acontece que esse segundo grupo, excluído no dia 20, havia sido alvo de um outro pedido da justiça ao Telegram, no dia 10. Esse pedido anterior havia sido menos abrangente, solicitava apenas dados do administrador do grupo. Segundo o Telegram, eles só tinham nesse momento informações desse administrador, coletadas para atender ao pedido do dia 10, e de mais ninguém. E não seria mais possível recuperar informações sobre os outros participantes do grupo. O Telegram diz que entregou o que tinha, mas a justiça considerou que não era suficiente e ordenou: Telegram bloqueado.

Veja a resposta publicada por Pavel Durov em seu canal no Telegram:

A missão do Telegram é preservar a privacidade e liberdade de expressão ao redor do mundo.

Em casos onde as leis locais vão contra essa missão ou impõem requerimentos tecnologicamente inviáveis, nós às vezes temos que deixar esses mercados. No passado, países como China, Irã e Rússia baniram Telegram devido a nossa postura baseada em princípios no tema de direitos humanos. Esses eventos, apesar de infelizes, são ainda preferíveis a trair nossos usuários e as crenças sobre as quais nos fundamentamos.

No Brasil, um tribunal requisitou dados que nos são tecnologicamente impossíveis de obter. Estamos apelando da decisão e esperando ansiosos pela solução final. Não importa o custo, vamos defender nossos usuários no Brasil e seu direito à comunicação privada.

Pavel Durov

Isso nos levanta três questões muito importantes:

Juízes lidando com tecnologia

A primeira delas é sobre o conhecimento técnico que deveria embasar decisões judiciais. O judiciário e a polícia precisam de bons assessores técnicos para auxilia-los nas decisões. Por exemplo, do primeiro grupo a ser excluído, mesmo que agisse imediatamente, o Telegram não teria dado algum.

Pior do que isso, veja esse trecho do ofício enviado pela Justiça do Espírito Santo ao Telegram:

… forneça, no prazo de 24 horas, os dados cadastrais com nome, nome de usuários, CPF, foto do perfil, status do perfil, e-mail, endereço, dados bancários e do cartão de crédito cadastrados, contatos fornecidos para recuperação de conta, dispositivos vinculados (incluindo IMEI, se houver), número de confiança
indicado para a autenticação de dois fatores e logs de criação (contendo IP, data, hora, fuso horário GMT/UTC e porta lógica) de todos os usuários do canal …

Você que é usuário de Telegram, me diga, em algum momento você cadastrou seu CPF ou sua conta bancária no aplicativo? Talvez você seja usuário do Premium e tenha cadastrado seu cartão de crédito. Mas, se for o caso, espero que seu cartão de crédito tenha sido tokenizado por um gateway de pagamento e o Telegram também não tenha acesso aos dados do cartão.

Como cumprir uma ordem impossível?

Não sei se Pavel Durov está de má vontade com a justiça brasileira. Ele é um sujeito polêmico e está sempre metido nesse tipo de confusão. Mas uma coisa está clara: mesmo que o Telegram não tivesse solicitado informações adicionais e tivesse agido imediatamente, não teria sido possível atender completamente o pedido da justiça. Veja esse trecho da política de privacidade do Telegram:

Telegram é um serviço de comunicação. Você informa seu número de telefone e dados básicos de conta (o que pode incluir um nome de perfil, foto de perfil e informação sobre você) para criar uma conta Telegram… Nós não queremos saber seu nome real, gênero, idade ou do que você gosta.

É claro que um juiz não tem a menor obrigação ou condições de saber o que é criptografia de ponta-a-ponta, política de retenção de dados, tokenização, etc. Mas deveria ter alguém ao lado dele para dizer: “então, excelência, isso aqui que o senhor está pedindo…”

Talvez, se o judiciário e a polícia estivessem melhor assessorados por técnicos competentes, não tivessem pedido ao Telegram dados que eles obviamente não têm. Talvez isso tivesse eliminado a necessidade de o Telegram responder com novas dúvidas. Nesse cenário em que o tempo foi crucial para o fracasso da iniciativa, talvez isso permitisse coletar os dados que o Telegram obviamente tinha (como número de telefone e IP) antes de o grupo ser apagado.

Sites e aplicativos na internet mundial

A segunda questão muito importante é sobre quanto empresas estrangeiras devem cumprir a legislação brasileira ao operar pela internet.

Por que então estamos com o Telegram bloqueado no Brasil? Se o Telegram não tinha os dados, por que o juiz determinou a suspensão do serviço? Porque no entendimento do juiz:

  1. O Telegram tinha os dados e não queria entregá-los. Por isso ele escreve “ante a recalcitrância do Telegram em cumprir…” O que volta para o ponto acima, o juiz não entendeu os detalhes técnicos do que estava pedindo.
  2. O Telegram deveria ter esses dados. Porque a legislação brasileira exige. O Marco Civil da Internet, em seu artigo 15°, diz:

O provedor de aplicações de internet constituído na forma de pessoa jurídica e que exerça essa atividade de forma organizada, profissionalmente e com fins econômicos deverá manter os respectivos registros de acesso a aplicações de internet, sob sigilo, em ambiente controlado e de segurança, pelo prazo de 6 (seis) meses, nos termos do regulamento.

Aqui também temos uma complicação ´técnica porque a legislação não diz quais registros de acesso, de quê, devem ser guardados. Absolutamente nenhuma aplicação guarda logs de TUDO o que o usuário faz ou acessa porque, obviamente, esses logs poderiam ser maiores que o próprio banco de dados da aplicação.

Ou seja, o Telegram poderia ter log de acesso dos usuários, com IP, hora de login e atividade, e não ter nenhuma informação sobre de que grupos cada usuário participava, tornando impossível vincular um id de grupo a uma lista de usuários. Tudo isso, sem descumprir a legislação. Acontece que o Telegram nem precisaria cumprir a legislação brasileira.

O Telegram e a lei brasileira

O Telegram não tem escritório no Brasil. Há um tempo alguns portais noticiaram, de uma forma bem sensacionalista, que o Telegram teria um escritório o representando no Brasil. Não é verdade, eles apenas contrataram um escritório de advocacia brasileiro para cuidar do registro da marca deles no Brasil.

Bom, é uma empresa com sede em Dubai e servidores todos fora do Brasil. Eles não estão sujeitos a nossa legislação. Nós deveríamos permitir que usuários brasileiros usassem os serviços deles?

Pense bem antes de responder. É claro que nós queremos que as empresas sejam responsáveis por seus atos, produtos e serviços e a legislação é uma maneira de tentar garantir isso. Mas você realmente quer que brasileiros não possam acessar sites, blogs, jogos, aplicativos e serviços de empresas e entidades que não têm uma sede brasileira? Isso não mataria boa parte da inovação que a internet pode trazer ao nos permitir colaborar em escala global?

Para que serviu o Telegram bloqueado?

O que nos leva ao terceiro ponto: será que o judiciário não deveria pensar duas vezes antes de bloquear serviços usados pela população? É claro que combater o nazismo é uma causa super prioritária e devemos empregar todos os esforços que pudermos nela. Mas o que estamos vendo aqui é uma trapalhada de comunicação entre o judiciário e o Telegram que, como consequência, prejudicou a vida dos 42 milhões de usuários ativos do app no Brasil. Muitos deles que usam o aplicativo para trabalhar e sustentar suas famílias. Se os dados que a justiça quer não existem, manter o Telegram bloqueado não está ajudando ninguém.

O Telegram entregou à Justiça os dados que eles tinham, o número de telefone e IP do administrador do grupo:

Captura de tela do ofício que deixou o Telegram bloqueado, mostrando os dados do administrador do grupo neonazista:
Usuário: #6129271951
Telefone: +51969506146
IP: 190.236.6.11, 11 Apr 2023, 4:16:36, UTC+0

Tanto o número de telefone quanto o endereço de IP são de Lima, no Peru:

Geolocalização do IP do administrador do grupo neonazista:
IP ADDRESS: 190.236.6.11
COUNTRY: Peru 
REGION: Lima
CITY: Lima
ISP: Telefonica del Peru S.A.A.
ORGANIZATION: Not available
LATITUDE: -12.0433
LONGITUDE: -77.0283

Faz sentido deixar o Telegram bloqueado para 42 milhões de pessoas por isso? Ainda mais por uma ordem impossível de ser cumprida?

Programe Música: Sonic Pi

É, oficialmente, meu novo hobby. Sonic Pi é uma ferramenta para criação de música ao vivo através de programação Ruby.

É divertidíssimo! Olha só, um exemplo do Sonic Pi tocando um Dó-Ré-Mi-Fá:

# Do-Re-Mi-Fa

use_synth :pluck

melody = [ :C, :D, :E, :F, 0, :F, :F, 0,
           :C, :D, :C, :D, 0, :D, :D, 0,
           :C, :G, :F, :E, 0, :E, :E, 0,
           :C, :D, :E, :F, 0, :F, :F, 0 ]

melody.each do |note|
  if note != 0 then
    play note
  end
  sleep 0.3
end

Numa tarde de domingo, escrevi o seguinte programa:

# Cyber Piano Blues #1
# Author: Elcio Ferreira
# https://elcio.com.br/

beat = 0.45

chords = [ chord(:A3, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:A3, :minor7),
           chord(:D4, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:A3, :minor7),
           chord(:E4, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:E4, :major7),
           ]

basses = [ :A2, :C3, :E3, :A2, :D3, :F3, :E3, :C3, :E3, :D3, :C3, :E3,
           :A2, :C3, :A2, :C3, :D3, :F3, :A2, :C3, :E3, :A2, :E3, :A2 ]

melody = [[ :A4, :B4, :C5, :E5, :B4, :C5, :E5, :Fs5, :A4, :B4, :C5, :E5, :B4, :C5, :E5, :Fs5,
            :E5, :B4, :C5, :E5, :B4, :C5, :E5, :C5,  :E5, :B4, :C5, :E5, :B4, :C5, :E5, :C5,
            :C5, :E5, :G5, :E5, :C5, :A4, :F4, :C5,  :C5, :E5, :G5, :E5, :C5, :A4, :F4, :C5,
            :A4, :B4, :C5, :E5, :B4, :C5, :E5, :C5,  :A4, :B4, :C5, :E5, :B4, :C5, :E5, :C5,
            :B4, :G4, :B4, :D5, :F5, :D5, :F5, :D5,  :B4, :G4, :B4, :D5, :F5, :D5, :F5, :D5,
            :B4, :C5, :E5, :Fs5,:E5, :Gs5,:E5, :D5,  :B4, :C5, :E5, :Fs5,:E5, :Gs5,:E5, :D5,
            ],
          [ :B4, :C5, :A4, :E5, :C5, :E5, :B4, :Fs5,
            :B4, :C5, :E5, :E5, :C5, :E5, :B4, :C5,
            :E5, :G5, :C5, :E5, :A4, :F4, :C5, :C5,
            :B4, :C5, :A4, :E5, :C5, :E5, :B4, :C5,
            :G4, :B4, :B4, :D5, :D5, :F5, :F5, :D5,
            :C5, :E5, :B4, :Fs5,:Gs5,:E5, :E5, :D5,
            ]
          ]


live_loop :melody do
  use_synth :piano
  idx = 0
  2.times do |melodyidx|
    4.times do |time|
      if time == 1 or time == 3 then
        melody[melodyidx].each do |tune|
          play tune
          sleep beat * (idx % 2 + 0.5)
          idx+=1
        end
      elsif time == 2 then
        melody[melodyidx].each do |tune|
          2.times do
            play tune
            if idx % 2 == 1 then
              sleep beat * 1
              play tune, pan: 0.5
            end
            sleep beat * 0.5
            play tune, pan: -0.5
            idx+=1
          end
        end
      else
        play :A5
        play_chord chord(:A4, :major7)
        play_chord chord(:A5, :major7)
        sleep beat * 6 * 8
        melody[1].each do |tune|
          play tune
          sleep beat/2
          play tune
          sleep beat/2
        end
      end
    end
  end
end

live_loop :chimes do
  sleep 12 * 4 * 4 * beat
  (12 * 4 * 4).times do
    sample :drum_cymbal_pedal
    sleep beat
  end
end

counter = 0
live_loop :drums do
  if counter % 4 == 0 and counter > 23 and counter < 48 then
    sample :drum_cymbal_open
  end
  sleep beat
  sample :drum_tom_hi_soft, pan: 0.4
  sleep beat * 1.5
  if counter > 23 then
    sample :drum_tom_hi_soft, pan: 0.4
  end
  sleep beat / 2
  if counter > 47 then
    sample :drum_tom_hi_soft, pan: 0.4
  end
  sleep beat
  sample :drum_snare_soft
  if counter % 24 == 0 then
    sample :drum_cymbal_closed, pan: 0.4
  end
  counter += 1
  if counter > 71 then
    counter = 0
  end
end

live_loop :progression_chords do
  use_synth :piano
  4.times do |variation|
    if variation > 0 then
      chords.each do |thechord|
        sleep beat
        play thechord, pan: -0.4
        sleep beat * 4
        play thechord, pan: -0.4
        sleep beat * 3
      end
    else
      chords.each do |thechord|
        sleep beat/2
        play thechord, pan: -0.4
        sleep beat * 2
        play thechord, pan: -0.2
        sleep beat * 1.5
        sleep beat/2
        play thechord, pan: 0
        sleep beat * 2
        play thechord, pan: 0.2
        sleep beat * 1.5
      end
    end
  end
end

live_loop :basses do
  use_synth :piano
  3.times do
    basses.each do |bass|
      2.times do
        play bass, amp: 1, pan: -0.7
        sleep beat/2
        play bass, amp: 1, pan: -0.7
        sleep beat * 3.5
      end
    end
  end
  4.times do
    basses.each do |bass|
      2.times do
        play bass, amp: 1, pan: -0.7
        sleep beat/2
        play bass, amp: 1, pan: -0.7
        sleep beat * 2.5
        play bass, amp: 1, pan: -0.7
        sleep beat
      end
    end
  end
end

live_loop :progression_melody do
  use_synth :piano
  5.times do |round|
    chords.each do |thechord|
      if round == 0 then
        play_pattern_timed thechord, beat/2, amp: 1, pan: 0.7
        sleep beat * 2
        play_pattern_timed thechord, beat/2, amp: 1, pan: 0.7
        sleep beat * 2
      elsif round == 1 then
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        sleep beat * 2
      elsif round == 2 then
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
      else
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        sleep beat * 4
      end
    end
  end
end

Se você não estiver afim de instalar o Sonic Pi para testar, e quiser saber como ficou meu blues:

Meu primeiro blues em Sonic Pi

Recomendo! Instala, testa, é divertido!

Otimização de performance prematura: não faça!

Otimização de performance é uma preocupação comum para quem está começando em programação, e muitas vezes mesmo programadores experientes tem dúvidas sobre esse assunto, o que é normal uma vez que o assunto é mesmo complexo. Não vou explicar nesse post tudo o que você precisa saber sobre performance, mas pretendo dizer o mais importante: quando você precisa se preocupar. Isso mesmo, porque um erro muito comum é ver os programadores se preocupar demais com performance, na hora errada.

Então vamos lá: nossos computadores são muito potentes hoje em dia. Muito. Dificilmente mudar a lógica de um cálculo, criar uma variável a menos, otimizar um loop, ou até concatenar menos strings vai fazer algum diferença sensível. Então, não pré-otimize, não otimize antes de medir.

Vamos mostrar um exemplo. Fiz em Python só porque eu gosto, mas a mesma coisa vale para sua linguagem favorita. Escrevi os dois arquivos a seguir:

strings1.py

tamanho=20
a='a'
for i in range(tamanho):
    a*=2
print(len(a))

strings2.py

tamanho=20
a='a' * (2**tamanho)
print(len(a))

São duas maneiras bem diferentes de se criar uma grande string. A segunda é muito mais eficiente que a primeira. Bom, veja os resultados da execução aqui na minha máquina:

$ time python strings1.py
1048576
real 0m0.023s
user 0m0.013s
sys 0m0.008s
$ time python strings2.py
1048576
real 0m0.021s
user 0m0.012s
sys 0m0.008s

Nenhuma diferença prática, certo? Aumentei a variável tamanho para 30, agora notamos diferença:

$ time python strings1.py
1073741824
real 0m1.375s
user 0m0.671s
sys  0m0.691s
$ time python strings2.py
1073741824
real 0m0.586s
user 0m0.235s
sys  0m0.344s

Agora a diferença é absurda, certo? Mas quando foi a última vez que você precisou concatenar strings de um bilhão de caracteres? O caso é: se suas strings vão chegar a esse tamanho, você provavelmente vai saber disso antes. Por exemplo, se você está fazendo um software de tratamento de imagens, parece óbvio que processamento pode ser um problema, certo? Se não, gastar seu tempo e esforço com otimização de performance provavelmente não vale a pena.

Aviso: o código do exemplo 1 é muito ruim, além de dar mais trabalho para escrever. Eu não estou sugerindo que você escreva código ruim de propósito, tá? Apenas que você não se preocupe demais com performance e não gaste seu tempo resolvendo problemas imaginários.

Há, porém, algumas situações em que tudo o que eu disse acima não vale. Nossos processadores são muito rápidos, nossas memórias também. Discos já não são tão rápidos assim. Bancos de dados, mais ou menos. A internet, bom, quem pode confiar na internet, né?

Então, se você vai consumir um webservice, e pode mudar seu algoritmo para fazer dez chamados ao invés de vinte, faça isso. Se vai escrever muito no disco, e puder reduzir em 20% as operações de escrita de arquivos, faça isso. Se escrevendo uma consulta SQL mais complexa você consegue fazer muito menos consultas ao banco de dados e usar mais índices, faça isso.

Eu faço mais ou menos assim em relação a performance:

  1. Vamos usar a internet? Otimize sempre.
  2. Vamos gravar grandes arquivos, ou fazer uso intensivo de disco? Otimize sempre.
  3. Cálculo científico, tratamento de imagens e outras operações de processamento massivo? Otimize sempre.
  4. Bancos de dados com milhões de registros e uso intenso? Otimize sempre.
  5. Uso comum de arquivos e bancos de dados? Cuide de não escrever nada muito ruim, e otimize se der problema.
  6. O resto todo? Escreva pensando em legibilidade, encapsulamento e reuso. Só otimize se tiver problemas.

Publiquei um vídeo sobre isso há um tempo, se você quiser dar uma olhada: Não pré-otimize.

Média de lista em Python, como calcular

Às vezes a gente tem a tendência de complicar as coisas. Semana passada, um amigo me perguntou se há alguma forma de calcular a média de uma lista em Python. Assim como há funções para calcular a soma dos elementos ou o maior elemento, ele esperava que houvesse uma para calcular a média.

Afinal, calcular a média de uma lista é uma necessidade comum, certo? Deve haver no Python algum jeito fácil de fazer, então. Quando eu disse que não, meu amigo gastou alguns segundos pesquisando e chegou nessa solução:

import numpy
l = [ 2, 5, 6.8, 9, 7]
avg = numpy.mean(l)

Funciona. Não é muito código. Mas tem alguns problemas:

  1. Cria uma dependência extra: será preciso ter o numpy instalado para que a aplicação funcione
  2. Complica um pouco mais o código: nem todo mundo sabe o que faz o método .mean(), fazendo com que outros programadores tenham que gastar um tempinho pesquisando
  3. Tem uma performance pior: ou, pelo menos, para os tamanhos de lista mais comum. A função de média do numpy é otimizada. Deveria portanto, ser mais rápida. Se você tiver que calcular centenas de médias de listas gigantescas, numpy vai fazer diferença. Mas não é o caso da maioria das aplicações. Se você for usar pouco a função mean() o custo de importá-la é maior que o de fazer o cálculo você mesmo.

E como fica esse cálculo? O jeito como eu recomendo calcular a média de uma lista em Python é esse:

l = [ 2, 5, 6.8, 9, 7]
avg = sum(l)/len(l)

A dica é: antes de procurar ou construir um módulo com a solução do seu problema, pense se não é um problema simples demais para isso. Se você fizer esse exercício, vai evitar escrever código como esse:

import calculations
x = calculations.sum(2, 7)

Ao invés de:

x = 2 + 7

E não, não tem filosofia, técnica ou estratégia que você posa usar para tentar me convencer de que o primeiro jeito é melhor do que o segundo.

Recursos “escondidos” do Python

Resposta que eu dei à pergunta: Quais são alguns dos recursos ocultos do Python? no Quora.


1. Atribuição múltipla (com tuple unpacking)

a, b, c = 1, 2, 3

2. Com isso dá para trocar o valor de variáveis

a, b = b, a

3. Encadeamento de comparadores

x = 3
print(1 < x < 5) # True

4. Generators

def fib(max):
    n1, n2 = 0, 1
    for i in range(max):
        yield n1
        n1, n2 = n2, n1 + n2
f = fib(20)
for i in f:
    print(i)

5. If em uma linha

aliquota = 0.05 if valor < 1000 else 0.07

6. List comprehension

# Quadrados dos números de 0 a 99
[i ** 2 for i in range(100)]

# Quadrados dos números de 0 a 99, apenas
# se o resultado não contém o dígito "4"
[i ** 2 for i in range(100) if not '4' in str(i**2)]

7. Invertendo uma string

a = a[::-1]

8. enumerate

for i, l in enumerate('palavra'):
    print (i, l, end=' / ')
# 0 p / 1 a / 2 l / 3 a / 4 v / 5 r / 6 a /

9. Unpacking estendido (só Python 3)

a, *b, c = "unpacking"
print(a, b, c)
# u ['n', 'p', 'a', 'c', 'k', 'i', 'n'] g

10. Dict comprehension

d = {i: i**2 for i in range(10)}
print(d)
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}

11. String formatting

dados={'nome': 'Joaquim', 'email': 'jsilva@fbi.gov'}
print('%(nome)s <%(email)s>' % dados)
# Joaquim <jsilva@fbi.gov>
print('{nome} <{email}>'.format(**dados))
# Joaquim <jsilva@fbi.gov>

12. zip

list(zip([1, 2, 3], [4, 5, 6]))
[(1, 4), (2, 5), (3, 6)]

Módulos Úteis

1. collections

import collections
print(collections.Counter('banana'))
# Counter({'a': 3, 'n': 2, 'b': 1})
d = collections.defaultdict(lambda:'...')
d['nome'] = 'Teste'
print(d['nome']) # Teste
print(d['idade']) # ...

2. pprint

from pprint import pprint
pprint(['a' * i for i in range(20)])
# ['',
#  'a',
#  'aa',
#  'aaa',
#  'aaaa',
#  'aaaaa',
#  'aaaaaa',
#  'aaaaaaa',
#  'aaaaaaaa',
#  'aaaaaaaaa',
#  'aaaaaaaaaa',
#  'aaaaaaaaaaa',
#  'aaaaaaaaaaaa',
#  'aaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaaa',
#  'aaaaaaaaaaaaaaaaaaa']

3. itertools

import itertools
for i in itertools.permutations("123"):
    print("".join(i), end=", ")
# 123, 132, 213, 231, 312, 321,
for i in itertools.product("01", repeat=3):
    print("".join(i), end=", ")
# 000, 001, 010, 011, 100, 101, 110, 111,

4. SimpleHTTPServer

➜  ~ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

5. webbrowser

import webbrowser
webbrowser.open('https://campus.visie.com.br/')

6. atexit

➜  ~ python3 -q
>>> def teste():
...     print('Bye!')
...
>>> import atexit
>>> atexit.register(teste)
<function teste at 0x10973a620>
>>> ^D
Bye!
➜  ~ _

7. base64

import base64
print(base64.b64encode(b'Teste'))
# b'VGVzdGU='

8. gzip

import gzip
print(gzip.open('teste.txt.gz').read())

Easter Eggs

Tente aí:

>> import this
>> import hello
>> import antigravity
>> from __future__ import braces

Como tornar seu script Python executável

Resposta que eu dei à pergunta: É possível escrever um script executável em Python? no Quora.


Sim!

No Windows, basta associar arquivos .py ao Python. Acredito que o instalador do Python para windows já faz isso. Feito isso, duplo clique no arquivo .py vai executá-lo.

No Linux, Mac, FreeBSD e assemelhados, basta colocar, na primeira linha do seu script:

#!/usr/bin/env python

Em seguida, torne seu script executável com o comando:

chmod +x seuscript.py

Claro, troque “seuscript” pelo nome do seu arquivo. Pronto, ele é executável. Você pode executar com:

./seuscript.py

Diferente do windows, a extensão não precisa ser .py, nem precisa ter extensão. Além disso, você pode mover o script para qualquer lugar no PATH do sistema e poderá executá-lo de qualquer diretório, sem precisar de ./ no início do comando. Por exemplo, pode fazer:

sudo mv ./seuscript.py /usr/local/bin/seucomando

Em seguida pode executar apenas:

seucomando

Sem ./ e em qualquer diretório.

Fish no Mac OS

Há um tempo, usando KDE Neon, troquei meu shell padrão para o fish. É tudo o que você pode querer num terminal. Autocompletar fantástico, syntax highlight e fácil de usar. Você pode testar o fish no navegador, sem instalar nada, no fish shell playground.

Agora estou de volta com um Mac. Segue um passo a passo de como fiz:

1. Instalar o Homebrew

Esta é a parte mais demorada e complicada do processo, mas a mais importante. Você precisa ter o XCode instalado. Em seguida, execute:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

O script vai te guiar no passo a passo da instalação

2. Instalar o fish

Com o Homebrew instalado, é bem fácil:

brew install fish

Depois disso, você pode abrir o terminal e executar “fish”.

3. Tornar o fish o shell padrão

Basta executar:

chsh -s /usr/local/bin/fish

Tendo feito isso, abra uma nova janela do terminal. O fish já deve carregar sozinho.

Software desejável

Um dos processos mais eficientes para melhorar a performance e o valor de um software é a análise de funil.

Isso é, você procura pelos “gargalos” de performance, aqueles pontos onde, se você melhorar as coisas, tudo vai fluir melhor.

Bem, software é feito para ser usado por pessoas. E aí está, geralmente, o gargalo mais óbvio para que um software dê o retorno que se espera dele.

Nós não somos racionais como gostamos de achar que somos. A maior parte de nossas motivações é emocional e intuitiva.

Por isso, se você construir software que as pessoas gostem de usar, isso pode com facilidade dobrar ou triplicar os retornos que seu software gera para seu cliente.

Isso inclui fatores objetivos, como responder rápido, ser fácil de usar, automatizar tarefas repetitivas e exigir menos passos para completar tarefas.

Mas inclui fatores subjetivos. Coisas que fazem as pessoas gostarem de um software.

Por exemplo, não basta que ele seja fácil de usar, precisa parecer fácil de usar. Não basta ser produtivo, precisa parecer produtivo.

Estou falando do valor de um bom design. O pessoal que desenvolve sites já descobriu isso há uns vinte anos.

Mas muita gente no mercado de software ainda está desperdiçando essa oportunidade. Você já reparou como são feios e complicados os ERPs, por exemplo?

É sobre pessoas

Você está no negócio de atender pessoas.

Se você desenvolve software, lembre-se de que alguém vai usá-lo. Para gerenciar coisas que importam para outras pessoas.

Se você desenvolve sites, lembre-se de que ele será acessado por pessoas. Para comunicar algo sobre outras pessoas.

Computadores são máquinas determinísticas. Ou pelo menos, são feitos para ser. Isso significa que, recebendo as mesmas entradas, um computador deveria se comportar sempre do mesmo jeito.

Seu comportamento pode ser completamente compreendido e previsto. E, se você é um programador, é exatamente isso que você estudou para fazer.

Já pessoas são o oposto. Não são máquinas, não são determinísticas. Seu comportamento também pode ser estudado e previsto, mas nunca com a mesma precisão. E isso exige um conjunto completamente diferente de conhecimento e ferramentas.

Talvez você precise gastar algum tempo para entender de pessoas. No post de amanhã vou falar sobre o porquê.

Aprenda os fundamentos: cores no CSS

Quando você se deparar com algum tipo de código, tenha a curiosidade de decifrá-lo.

Me impressiono com a quantidade de programadores que precisam escrever CSS com regularidade e nunca pararam para entender o significado dos código de cores.

É simples: uma cor RGB é composta de três números, representando as cores vermelho (R), verde (G) e azul (B). Cada um desses números pode ir de 0 a 255 (1 byte).

Então o vermelho vivo é:

rgb(255, 0, 0)

Que também pode ser escrito como:

rgb(100%, 0, 0)

Ou, em hexadecimal (255 = FF):

#FF0000

As cores que podem ser “arredondadas” para duplas de letras iguais, como essa, podem também ser escritas assim:

#F00

E é isso. Da próxima vez que você escrever uma cor, vai saber o que significa. Agora pesquisa sobre RGBA, você via ver como fica fácil entender.

Mas não é só sobre cores. Faça isso sempre que se deparar com qualquer tipo de código, tente entender o que ele significa, você vai gastar um pouquinho de tempo no início, mas a vida vai ficar muito mais fácil depois.

Você está no negócio do conhecimento

Joel Spolsky diz que um bom programador pode ser 5 ou 10 vezes mais produtivo que um programador medíocre.

Esses números, postos desse jeito, talvez não dêem a dimensão do que isso significa. Você preferiria trabalhar com alguém porque ele é 10% mais produtivo? Que tal 20%? Com certeza!

Não estamos falando de um ganho de 10% ou 20%, estamos falando de um ganho de 400% a 900%!

Você quer ser esse programador? Então vai estudar, filhão!

Eu sei que tem assuntos demais para ser estudados, que é difícil escolher qual linguagem, framework, ferramenta ou técnica aprender em seguida. Mas não use isso como desculpa! Larga um pouco o Free Fire e investe na sua carreira.

Faço uma aposta com você: meia hora por dia, por seis meses. Daqui a seis meses você pede um aumento, ou arruma um emprego melhor. Duvido que não funcione.

Não seja escravo das suas ferramentas

Muita gente que, como eu, tem um blog, usa o plugin Yoast SEO para WordPress. É muito bom, uma escolha óbvia. Ele praticamente lê seu texto e te diz o que você tem que fazer para melhorar a indexação.

O problema? Muitas vezes, otimizar seu texto para uma determinada palavra-chave o torna chato de ler. Seu texto fica mais ou menos assim:

… Ao usar um plugin de SEO para WordPress, você corre o risco de escrever um texto mecânico. É verdade que plugins de SEO para WordPress são uma coisa boa, mas você precisa tomar cuidado para não deixar seu plugin de SEO para WordPress mandar em você…

Você quer apenas ser encontrado? Tem um monte de sites por aí tão cheios de publicidade que tornam quase impossível ler o que está escrito. O objetivo é ser encontrado e gerar um clique patrocinado, apenas isso. Se é isso o que você está construindo, vá em frente, siga as regras do plugin e você vai poupar um bocado de tempo.

Mas se seu objetivo é que as pessoas encontrem, leiam e entendam o que você está escrevendo, então seguir cegamente as regras não é a melhor decisão.

Escreve para pessoas, depois faça o que for possível para agradar os robôs.

Há um tempo que eu tenho usado o Pylint em alguns projetos. Ele me avisa se eu deixo de seguir algum padrão de código. Ele até dá uma nota para o meu código!

Mas o recurso mais legal do Pylint é poder fazer isso:

import config # pylint: disable = relative-import

Ou seja, não preciso seguir as regras cegamente.

Você também pode decidir quando quebrar as regras. Escolha com cuidado.

Não é sobre quantas linhas de código você escreve

Parece haver uma certa fixação entre os programadores, principalmente os menos experientes, em quantas linhas de código são necessárias para resolver determinado problema.

Às vezes isso é bom. Veja como ler um arquivo texto em Java:

import java.io.*; 
public class ReadingFromFile 
{ 
    public static void main(String[] args) throws Exception 
    { 
	FileReader fr = 
	new FileReader("arquivo.txt"); 

	int i; 
	while ((i=fr.read()) != -1) 
	    System.out.print((char) i); 
    } 
} 

Agora compare com a mesma coisa em Python:

print(open('arquivo.txt').read())

Nesse caso, parece óbvio que a resposta em Python é muito melhor, não? Agora olhe esse código em JavaScript:

urlscore = url.indexOf('http') ? -1 : (url.indexOf('https://')+1)*5 + 
                                      (url.split('/')[2].indexOf('www')?1:0)*2 + 
                                      (url.split('/')[1].indexOf('@')>-1?-1:1)*3

Uau! O sujeito reduziu a função inteira a uma única expressão! Parece uma boa ideia pra você? Coitado de quem tiver que dar manutenção nisso!

Seu inimigo não é a quantidade de código, é a complexidade. É difícil dar uma boa definição técnica de complexidade, mas você a reconhece quando vê.

Seja conservador (não, não é sobre política)

Eu tenho andado por aí com um caderno. Não um desses Moleskines descolados. O meu é um clássico Tilibra de dez matérias, que você pode comprar por doze reais em qualquer papelaria.

Durante milênios a humanidade, ou a parte dela que tinha o privilégio de saber escrever, escreveu a mão. Eu, que vivo de tecnologia, acho uma maravilha poder escrever com um teclado, como estou fazendo agora.

Mas percebi que alguma coisa diferente deve acontecer no cérebro quando a gente escreve a mão. E isso está me fazendo um bem enorme.

A gente usa teclados há duas gerações. Telas touch, há uns quinze anos.

Talvez, daqui a cinquenta anos, a humanidade esteja lamentando o quanto a gente perdeu por deixar de escrever e terceirizar nossa memória. Por deixar que os alunos simplesmente tirem fotos da lousa ao final da aula.

Talvez não. Mas por que correr esse risco? Você pode continuar usando teclados, esfregando suas digitais em pequenas telas de vidro ou falando com seu telefone. Mas experimente o velho e bom papel com caneta, pode funcionar pra você.

O ano do Linux no Desktop (não como você esperava)

O Windows 10 vai incluir um kernel Linux completo. O ChromeOS é baseado no kernel Linux.

Seria 2019, finalmente, o “ano do Linux no Desktop”?

Eu não certeza das implicações disso.

Eu sei que o que você esperava era a popularização do Gnome. Ou do KDE, ou XFCE, ou Enlightenment, ou Mate… Tanto faz, certo? Não importa qual interface gráfica, se o coração for Linux.

Então, será que faz diferença se a interface é Windows ou ChromeOS? O resultado final é que você vai poder escrever aplicações baseadas no Linux para rodar em todo lugar.

E, sinceramente, a web já tinha tornado essa discussão meio irrelevante.

Exceto para nós, programadores, que vamos poder desenvolver usando qualquer sistema operacional. Para o resto do mundo, a maior parte do tempo, o sistema operacional é o navegador.

Quanto mais óbvio, melhor

Quando você está escrevendo código, pense sempre em quem vai ter que lê-lo no futuro. Pode ser você mesmo. Pode ser você mesmo, daqui a cinco, às duas da manhã, correndo para consertar um bug.

É por isso que padrões e convenções são uma ideia tão boa.

Quanto tempo você já passou olhando o código de alguma aplicação, tentando descobrir onde estão as coisas? No web2py, um dos meus frameworks favoritos, quando você cria uma nova aplicação, a pasta de código se parece com isso:

Aplicação nova em web2py, ainda sem nenhum código.

Web2py é um framework MVC, que, você sabe, é a sigla para model, view e controller. Para acessar o banco de dados você escreve um model. E como se chama a pasta onde estão seus models? Ok, models. E as regras de negócio devem ir num controller. E onde estão seus controllers? Na pasta controllers, claro. E as views na pasta views.

Zero esforço para entender, zero esforço para decorar.

Eu sei que é bem pouco esforço decorar que, no seu novo framework da moda, as views estão dentro de /presentation/templates/html, os controllers em /app/core/controllers e os modelos em /persistence/rdbs. Mas pouco é infinitamente mais do que zero. E, acredite, esses pequenos esforços, somados, fazem um bocado de diferença.

Site não seguro – como resolver de graça com Let’s Encrypt

No começo de 2017, o Google Chrome passou a mostrar um aviso para os usuários, com o texto “não seguro” na barra de endereço quando um site sem HTTPS pede dados do usuário. Classificou a maioria dos sites como “site não seguro”. Assim:

Aviso de site não seguro do Chrome

Essa mensagem aparecia apenas em situações onde o site potencialmente ia coletar dados dos usuários. Basicamente, quando havia um formulário na tela. Principalmente formulários de login, mas a mensagem aparecia para praticamente qualquer formulário. Logo, durante todo o ano passado, você poderia manter um site de conteúdo sem HTTPS, sem problema nenhum, desde que não tivesse formulários.

Recentemente, porém, o Google passou a avisar site não seguro para qualquer site sem HTTPS. Assim, até o Pudim, um site que não tem formulário, nem scripts, nem nada, só uma foto de um pudim, está marcado, veja:

Site Pudim marcado pelo Chrome como site não seguro
Até o Pudim agora é um site não seguro, pobre Pudim 🙁

Tenho um site não seguro. Como resolver? Let’s Encrypt!

Essa iniciativa do Google Chrome não está sozinha. Faz parte de um esforço de várias frentes para tornar a web mais segura. O próprio Google anunciou que está privilegiando nas buscas sites com HTTPS. Quer dizer que, ao estar marcado como site não seguro, seu site não apenas vai assustar os usuários que receber, também vai receber menos usuários.

O próprio Google Chrome, junto com empresas como GitHub, Facebook, Cisco e Akamai, patrocinam uma iniciativa chamada Internet Security Research Group, que oferece, através do Let’s Encrypt, chaves SSL grátis e automáticas para qualquer site.

Assim, se o seu provedor dá suporte a Let’s Encrypt, você provavelmente pode ter seu site marcado como seguro em poucos cliques. Meu hosting predileto, por exemplo, é a Dreamhost. Se você hospeda seu site lá, pode ativar SSL em seu site em três cliques, aqui:

Página Secure Hosting no painel da Dreamhost
Viu ali? Let’s Encrypt SSL.

Se você mantém seus próprios servidores, dedicados ou VPS, você vai ter que instalar o Let’s Encrypt você mesmo. O processo é bastante simples. Expliquei nesse vídeo:

HTTPS com Let’s Encrypt

Mantenha seus servidores enxutos

Foi divulgada ontem uma vulnerabilidade no servidor de compartilhamentos Samba, usado por máquinas Linux e FreeBSD para compartilhar arquivos e recursos em redes Windows. É uma falha grave, simples de explorar, e que afeta versões do Samba desde a 3.5.0, lançada há sete anos.

Então, se você usa Linux, confira se você tem o Samba instalado. Se tiver, confira a versão menor (aquele terceiro número no código da versão). Se você estiver usando uma das seguintes, você está seguro: 4.6.4, 4.5.10 ou 4.4.14.

Se não. Você pode fazer uma das seguintes coisas:

  1. verificar se há atualização do Samba para sua distribuição, e se a versão mais atualizada é uma dessas acima; ou
  2. baixar o código fonte e compilar o Samba você mesmo, de preferência da versão 4.6.4; ou
  3. desligar o serviço vulnerável, adicionando ao seu smb.conf a linha abaixo:
    nt pipe support = no

    E em seguida reiniciando o Samba; ou

  4. desinstalar o Samba

A última alternativa pode parecer a mais preguiçosa, e talvez você simplesmente não possa cogitá-la. Mas eu recomendo que você se pergunte, antes de qualquer outra atitude: eu preciso mesmo desse serviço? Dessa vez foi uma falha no Samba, mas praticamente todo dia saem atualizações de segurança para os diversos softwares e serviços que você pode instalar em seu sistema. Cada software não utilizado que você mantém instalado aumenta suas chances de ter problemas de segurança e suas preocupações com atualizações de versão.

Nesse caso, menos é mais. Reduza os pacotes que você tem instalados aos essenciais, removendo tudo o que você não usa. Principalmente em servidores. Isso vai tornar suas máquinas mais seguras e vai tornar mais fácil para você manter tudo atualizado.

Assine a companhe os boletins de segurança dos softwares que você usa. Você não quer correr o risco de não ficar sabendo de uma atualização crítica e ter seu sistema vulnerável simplesmente por não ter sido avisado, não é?

Por fim, é importante que você saiba que a essa falha de segurança no Samba é especialmente preocupante porque muitos dispositivos NAS e outras soluções de armazenamento de dados usam Samba. Então se você possui um equipamento de armazenamento de dados, é bom investigar se ele usa Samba e está vulnerável a essa falha.


PS: obrigado ao Rodrigo por me avisar.