Publicado em 15 de Novembro de 2020 às 12:43

Última atualização em 15 de Novembro de 2020 às 20:29

Python + VS Code + Black: Como formatar o seu código Python no VS Code automaticamente usando Black

python
Acompanhe esse conte√ļdo pelo YouTube

E aí, beleza?

Hoje eu vou te mostrar uma maneira de configurar o VS Code pra ele formatar automaticamente o seu código usando o Black sempre que você salvar um arquivo Python. Por exemplo, esse é um código que não foi formatado pelo Black:

"""Exemplo Black"""

def minha_função_muito_muito_muito_muito_looooooooooooooooooooooonga(nome, idade, email): pass

def minha_função(*args) :
    return  True

resultado=minha_função('a', 'b', 'c',
                       'd', 'e', 'f',)

minha_lista = ['fabio','josi',]

print( minha_lista )

E aqui está o mesmo código após a mágica do Black:

"""Exemplo Black"""


def minha_função_muito_muito_muito_muito_looooooooooooooooooooooonga(
    nome, idade, email
):
    pass


def minha_função(*args):
    return True


resultado = minha_função(
    "a",
    "b",
    "c",
    "d",
    "e",
    "f",
)

minha_lista = [
    "fabio",
    "josi",
]

print(minha_lista)

O que mudou de um código para o outro:

Black

Se você já sabe o que é o Black, pode ir para a próxima seção.

Se voc√™ n√£o sabe, √© o seguinte: O Black √© um formatador de c√≥digo Python. Ele analisa o seu c√≥digo e faz as altera√ß√Ķes que ele entende como necess√°rias.

Uma coisa muito legal de usar um formatador como o Black √© que o c√≥digo sempre vai ter a mesma cara. Independente do projeto, independente de quem escreveu, o c√≥digo sempre vai ter uma apar√™ncia semelhante, e com isso focamos apenas no que realmente interessa, que √© o conte√ļdo do arquivo, e n√£o como esse arquivo est√° formatado.

Usar o Black significa ter uma coisa a menos para se preocupar. Use o Black e não se preocupe com formatação nunca mais. Deixe essa preocupação com o Black.

Recomendo a leitura dessa se√ß√£o da documenta√ß√£o do Prettier. O Prettier √© um formatador de JavaScript. √Č o Black do JavaScript. Eles respondem muito bem a pergunta “Por que usar o Prettier?”. D√° pra fazer um bom paralelo com o Black.

Agora que sabemos o que é o Black e sabemos alguns dos motivos para usá-lo, vamos seguir em frente.

Instalando o Black

Como eu disse no come√ßo da aula, eu vou mostrar uma maneira de chegar onde queremos, mas voc√™ tem v√°rias op√ß√Ķes. Eu vou seguir um caminho e voc√™ faz as altera√ß√Ķes que fizerem sentido para a sua situa√ß√£o.

A primeira etapa é no terminal, vamos instalar o Black:

pip install black

Pra checar que deu tudo certo você pode rodar o comando

black --version

e você deve ter um resultado parecido com o meu:

black, version 20.8b1

Agora vamos para o VS Code.

Settings do VS Code

Se você já alterou o arquivo settings.json do VS Code alguma vez na vida, pode ir para a próxima seção.

Caso contr√°rio, √© o seguinte: A √ļnica coisa que eu assumo agora √© que voc√™ tem o VS Code instalado no seu computador e voc√™ consegue rodar c√≥digo Python nele. Eu tenho um v√≠deo ensinando a fazer isso, se voc√™ precisar.

Tendo o VS Code e sabendo rodar c√≥digo Python nele, o pr√≥ximo passo √© entender que o VS Code √© super customiz√°vel. Voc√™ tem algumas formas de alterar as configura√ß√Ķes padr√£o do VS Code, uma das formas mais pr√°ticas √© a que vou te mostrar agora:
1. Aperte a tecla F1, isso faz uma janelinha aparecer no centro da sua tela.
2. Digite settings no campo de busca dessa janelinha.
3. Clique na primeira op√ß√£o, “Preferences: Open Settings (JSON)”.

Esse procedimento abre o arquivo settings.json. Esse arquivo pode estar vazio, apenas com duas chaves, tipo isso:

{
}

Ou ele pode ter algumas configura√ß√Ķes que voc√™ j√° customizou. Eu acredito que pelo menos alguma coisa deve ter nesse seu arquivo, por exemplo:

{
    "python.languageServer": "Pylance",
    "python.pythonPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",
}

Rodando Black automaticamente no VS Code

Vamos criar um arquivo Python chamado “aula_black.py” e escrever um c√≥digo bem simples:

print( 'oi' )

Aperte Ctrl+S para salvar esse arquivo (ou clique em File -> Save).

Naturalmente, nada aconteceu com esse arquivo, porque ainda n√£o configuramos o formatador autom√°tico.

Para garantir que est√° tudo certo, vamos executar esse arquivo no terminal. Voc√™ tem diversas op√ß√Ķes para executar esse arquivo, as mais f√°ceis:

Se tudo estiver funcionando corretamente, o seu programa vai rodar sem erros e voc√™ ver√° um “oi” na sua tela.

Seguindo em frente, vamos escrever algumas linhas no arquivo settings.json:

// Formatar com Black automaticamente
"python.formatting.provider": "black",
"python.formatting.blackPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\black.exe",
"python.formatting.blackArgs": ["--line-length", "88"],
"[python]": {
    "editor.formatOnSave": true,
},

A configura√ß√£o "python.formatting.provider" determina qual ferramenta vamos usar para formatar nosso c√≥digo. Temos tr√™s op√ß√Ķes: autopep8, black e yapf. Para a aula de hoje vamos usar o black.

A configura√ß√£o "python.formatting.blackPath" determina onde est√° o Black no seu computador. Essa configura√ß√£o tem um valor padr√£o que √© simplesmente "black". Dependendo da sua situa√ß√£o e das suas configura√ß√Ķes voc√™ nem precisa inserir essa linha, basta usar o valor padr√£o. No meu caso faz sentido passar o caminho completo do Black.

A configura√ß√£o "python.formatting.blackArgs" determina as op√ß√Ķes que v√£o ser passadas para o Black quando ele for executado. Se voc√™ digitar black -h no terminal, voc√™ consegue ver as op√ß√Ķes que voc√™ pode usar aqui. A op√ß√£o que eu configurei no meu arquivo settings.json (–line-length) determina o comprimento m√°ximo que uma linha pode ter. O Black j√° usa por padr√£o um limite de 88 caracteres, ent√£o voc√™ pode ignorar essa linha, se quiser.

A configura√ß√£o "editor.formatOnSave" determina que o arquivo deve ser formatado automaticamente sempre que for salvo. Essa configura√ß√£o est√° dentro do bloco "[python]", as configura√ß√Ķes dentro desse bloco s√≥ valem para os arquivos Python.

Salve o arquivo settings.json e volte para o arquivo “aula_black.py”. Aperte Ctrl+S (ou v√° em File -> Save) e veja a m√°gica acontecer. Pronto. Agora sempre que voc√™ salvar os seus arquivos Python o Black vai atuar.

E o artigo ainda n√£o acabou. √Č prov√°vel que al√©m do Black voc√™ use outras ferramentas como o isort, o flake8 e o pylint. Vamos fazer algumas configura√ß√Ķes para garantir que essas ferramentas n√£o v√£o discordar do Black.

Compatibilidade isort

Crie dois arquivos em uma mesma pasta. O primeiro chamado “meu_modulo_muito_grande_e_cheio_de_funcoes.py”, com esse c√≥digo:

def uma_funcao_com_um_nome_enorme():
    pass


def mais_uma_funcao():
    pass


def outra_funcao():
    pass

E outro chamado “aula_black_isort.py” com esse c√≥digo:

from meu_modulo_muito_grande_e_cheio_de_funcoes import uma_funcao_com_um_nome_enorme, mais_uma_funcao, outra_funcao
from math import pi

Salvando o arquivo “aula_black_isort.py”, ele fica desse jeito, pois o Black atua nele:

from meu_modulo_muito_grande_e_cheio_de_funcoes import (
    uma_funcao_com_um_nome_enorme,
    mais_uma_funcao,
    outra_funcao,
)
from math import pi

Clique com o bot√£o direito no seu c√≥digo e selecione a op√ß√£o “Sort Imports”.
Agora o código fica assim:

from math import pi

from meu_modulo_muito_grande_e_cheio_de_funcoes import (
    mais_uma_funcao, outra_funcao, uma_funcao_com_um_nome_enorme)

Salve o arquivo de novo. O código foi alterado pelo Black novamente:

from math import pi

from meu_modulo_muito_grande_e_cheio_de_funcoes import (
    mais_uma_funcao,
    outra_funcao,
    uma_funcao_com_um_nome_enorme,
)

Execute o comando “Sort Imports” mais uma vez e perceba que o c√≥digo mudou de novo:

from math import pi

from meu_modulo_muito_grande_e_cheio_de_funcoes import (
    mais_uma_funcao, outra_funcao, uma_funcao_com_um_nome_enorme)

Temos um problema. Essas duas ferramentas não estão concordando sobre como formatar esses imports. Resolver é muito fácil, basta adicionar essa linha no arquivo settings.json:

// Compatibilidade Black-isort
"python.sortImports.args": ["-m3", "--tc", "-fgw 0", "--up", "-n", "-l 88"],

Esses comandos fazem a formata√ß√£o dos imports seguir o padr√£o do Black. Para mais informa√ß√Ķes, clique aqui.

Volte para o arquivo “aula_black_isort.py” e execute o comando “Sort Imports” novamente, o c√≥digo vai ficar assim:

from math import pi

from meu_modulo_muito_grande_e_cheio_de_funcoes import (
    mais_uma_funcao,
    outra_funcao,
    uma_funcao_com_um_nome_enorme,
)

Igual ao Black!

E tem mais uma coisa que podemos fazer: em vez de clicar em “Sort Imports” podemos configurar o VS Code para organizar os imports automaticamente sempre que salvarmos o nosso arquivo.

Lá no arquivo settings.json adicione essa configuração dentro do bloco "[python]":

"editor.codeActionsOnSave": {
    "source.organizeImports": true
}

O seu arquivo settings.json deve estar desse jeito:

{
    // Suas outras configura√ß√Ķes
    // ...

    // Formatar com Black e organizar imports automaticamente
    "python.formatting.provider": "black",
    "python.formatting.blackPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\black.exe",
    "python.formatting.blackArgs": ["--line-length", "88"],
    "[python]": {
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        }
    },

    // Compatibilidade Black-isort
    "python.sortImports.args": ["-m3", "--tc", "-fgw 0", "--up", "-n", "-l 88"],
}

Agora sempre que você salvar seus arquivos Python o VS Code vai formatá-los automaticamente com o Black e organizar os imports com o isort. Show. Vamos para a próxima ferramenta.

Compatibilidade flake8

Crie um arquivo chamado “aula_black_flake8.py” e escreva esse c√≥digo:

inicio = 0
nome = "fabio"

iniciais_nome = nome[inicio:inicio+3]

print(iniciais_nome)

E no arquivo settings.json escreva isso:

// Compatibilidade Black-Flake8
"python.linting.flake8Enabled": true,
"python.linting.flake8Path": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\flake8.exe",

A primeira configuração é para habilitar o flake8 no VS Code, e a segunda é pra dizer onde o executável está. Lembre-se de alterar o caminho do flake8 para o valor adequado no seu caso. E se você não tem o flake8 instalado, você precisa rodar um pip install flake8.
Agora volte para o código e dê um Ctrl+S, o código ficará assim:

inicio = 0
nome = "fabio"

iniciais_nome = nome[inicio : inicio + 3]

print(iniciais_nome)

Perceba que o flake8 reclama de uma escolha que o Black faz: whitespace before ':' (E203). O flake8 não quer espaços antes dos dois pontos. Vamos falar para o flake8 ignorar essa regra. No arquivo settings.json, escreva:

"python.linting.flake8Args": ["--ignore=E203", "--max-line-length=88"],

A opção ignore=E203 diz para o flake8 ignorar a mensagem de que existe um espaço antes dos dois pontos, e a opção max-line-length é para definir o limite de caracteres de uma linha. Estamos seguindo o padrão do Black de 88.

Agora acrescente esse c√≥digo ao arquivo “aula_black_flake8.py”:

concatenacao_muito_grande = "uma string enoooooooooooooooooooooooooooooorme" + "uma string ok" + "fabio" + "josi"

O Black vai formatar esse código para:

concatenacao_muito_grande = (
    "uma string enoooooooooooooooooooooooooooooorme"
    + "uma string ok"
    + "fabio"
    + "josi"
)

E o flake8 vai reclamar: line break before binary operator (W503). Ele n√£o concorda com a escolha do Black de quebrar a linha antes do +.

Pra resolver isso, edite o campo "python.linting.flake8Args" no arquivo settings.json acrescentando a mensagem W503:

"python.linting.flake8Args": ["--ignore=E203, W503", "--max-line-length=88"],

Pronto. Agora o flake8 n√£o discorda mais das escolhas do Black.

Já temos duas ferramentas compatíveis com o Black, vamos para a próxima.

Compatibilidade pylint

Pra configurar o pylint, vamos escrever isso no arquivo settings.json:

"python.linting.pylintEnabled": true,
"python.linting.pylintPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\pylint.exe",

A primeira configuração é para habilitar o pylint no VS Code, e a segunda é pra dizer onde o executável está. Lembre-se de alterar o caminho do pylint para o valor adequado no seu caso. E se você não tem o pylint instalado, você precisa rodar um pip install pylint.

Agora precisamos nos atentar a duas coisas. A primeira é que até pouco tempo atrás existiam duas mensagens do pylint que conflitavam com o Black, mas elas foram removidas do pylint na versão 2.6, então eu vou assumir que você está usando a versão mais recente do pylint e nós não precisamos nos preocupar com essas mensagens.

A segunda coisa pra ficar atento √© que existem diferen√ßas entre rodar o pylint pelo terminal e rodar o pylint pelo VS Code com as configura√ß√Ķes padr√£o do VS Code. Por padr√£o, o VS Code s√≥ mostra as mensagens do tipo Error (E), do tipo Fatal (F), e algumas do tipo Warning (W). Ele n√£o mostra as mensagens do tipo Convention (C), Refactor (R) e algumas do tipo Warning (W).

Se você quiser continuar com o comportamento padrão do VS Code e só mudar o tamanho máximo de uma linha, escreva esse código no arquivo settings.json:

"python.linting.pylintArgs": [
    "--disable=all",
    "--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode",
    "--max-line-length=88",
],

Eu n√£o uso essas configura√ß√Ķes, eu gosto de mostrar mais mensagens, eu habilito v√°rias mensagens de Convention e Refactor, e desabilito v√°rias mensagens que me atrapalham, mas esse artigo √© pra falar do Black e n√£o do pylint, ent√£o vamos seguir em frente.

Pra testar que o pylint est√° funcionando, vamos criar um arquivo chamado “aula_black_pylint.py” e escrever esse c√≥digo:

return True

O pylint deve achar esse erro:

1,0,error,return-outside-function:Return outside function

Com isso temos mais uma ferramenta funcionando e compatível com o Black.

No VS Code, se voc√™ apertar Ctrl+Shift+M voc√™ abre a aba de problemas (“Problems”), nela aparecem os problemas que nossas ferramentas encontraram. √Č bem legal ficar de olho nessa aba para melhorar o nosso c√≥digo.

Outra coisa legal que voc√™ pode fazer √© clicar na aba Output e selecionar Python. Voc√™ vai ver que sempre que voc√™ salva o seu arquivo, um novo output √© gerado, com os resultados das execu√ß√Ķes do black, pylint, flake8, etc.

Pronto! Ferramentas configuradas.

A vers√£o final do seu arquivo settings.json deve ficar dessa forma:

{
    // Suas outras configura√ß√Ķes, por exemplo:
    "python.languageServer": "Pylance",
    "python.pythonPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\python.exe",

    // Formatar com Black e organizar imports automaticamente
    "python.formatting.provider": "black",
    "python.formatting.blackPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\black.exe",
    "python.formatting.blackArgs": ["--line-length", "88"],
    "[python]": {
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        }
    },

    // Compatibilidade Black-isort
    "python.sortImports.args": ["-m3", "--tc", "-fgw 0", "--up", "-n", "-l 88"],

    // Compatibilidade Black-Flake8
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Path": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\flake8.exe",
    "python.linting.flake8Args": ["--ignore=E203, W503", "--max-line-length=88"],

    // Compatibilidade Black-Pylint
    "python.linting.pylintEnabled": true,
    "python.linting.pylintPath": "C:\\Users\\fabio\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\pylint.exe",
    // Modifique essa configuração, habilitando e desabilitando as mensagens de acordo com suas preferências
    "python.linting.pylintArgs": [
        "--disable=all",
        "--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode",
        "--max-line-length=88",
    ],

    // Suas outras configura√ß√Ķes
    // ...
}

Conclus√£o

Agora você sabe como fazer o VS Code formatar o seu código Python automaticamente usando o Black.

Qualquer d√ļvida, sugest√£o ou corre√ß√£o √© s√≥ deixar um coment√°rio.

Um abraço, falou!


Compartilhe

Gostou deste artigo? Compartilhe para esse conte√ļdo chegar a mais pessoas!

N√£o perca nenhum conte√ļdo!

Se você quiser receber um e-mail sempre que eu postar um artigo novo, basta se inscrever aqui:


Artigos que podem ser do seu interesse

11 de Setembro de 2020

Tutorial Django - Cadastro e login de usu√°rios apenas com e-mail e senha

Aprenda a fazer o cadastro e login de usu√°rios apenas com e-mail e senha.

python, django

11 de Setembro de 2020

Tutorial Django - Criando um modelo de usu√°rio personalizado (Custom User Model)

Aprenda a criar um modelo de usu√°rio personalizado nos seus projetos Django.

python, django

20 de Maio de 2020

Fun√ß√Ķes com valores padr√£o mut√°veis: Qual √© o problema?

Atrav√©s de um exemplo simples entendemos por que n√£o devemos definir fun√ß√Ķes com valores padr√£o mut√°veis.

python

20 de Abril de 2020

Resenha - Think Python (Pense em Python)

Meus coment√°rios sobre esse livro.

python, resenhas