Criar e Executar um Aplicativo


Criando um aplicativo do Flet

Instruções para o instalação do Git podem ser vista em
Git e GitHub, nesse site.

O flet inclui uma rotina que pode ser usada para gerar um aplicativo mínimo, que pode ser aumentado com os widgets e comandos do usuário. Para usar a criação automática do projeto básico é necessário ter o git instalado no computador. Após ter os requisitos instalados executamos flet create que gera um esqueleto básico de um aplicativo, contendo alguns widgets:

# Para criar o aplicativo de nome <teste> crie um diretório com esse nome e mude para ele
$ mkdir teste
$ cd teste

# o aplicativo pode ser criado apenas com
$ flet create

# o aplicativo pode ser rodado com
$ flet run

Essas ações geram a seguinte estrutura de diretórios:

  • src/main.py é o ponto de entrada do aplicativo Flet. Nele se pode colocar uma página ou janela (objetos containers do flet) contendo ramificações para outras páginas, botões e componentes de exibição de conteúdo. Ele termina com flet.app(main), o que inicializa e roda o aplicativo. É possível definir um ponto de entrada diferente especificando no argumento --module-name <argumento>.
  • assets é um diretório [opcional] que contém arquivos auxiliares do aplicativo, como imagens, som, texto e outros arquivos necessários. Ele também pode conter imagens usadas como ícones de pacotes e telas iniciais. Se existir apenas o ícone icon.png (que pode ser nos formatos suportados como .bmp, .jpg, .webp) ele será usado como uma imagem de origem para gerar todos os ícones e telas iniciais para todas as plataformas.
  • pyproject.toml contém os metadados do aplicativo, com uma lista suas dependências. Ele controla o processo de compilação. A lista de dependências do projeto deve conter pelo menos o pacote flet.
Caso se use o gerenciador de ambiente uv o comando é uv run flet create.
Usando o gerenciador de ambiente poetry o comando é poetry run flet create.

Um projeto de aplicativo pode ser criado diretamente (sem a existência prévia do diretório).

# para criar um aplicativo com o nome <nome_do_projeto>
# <nome_do_projeto> será usado como nome do diretório que recebe o aplicativo.
$ flet create <meu_aplicativo_flet>

# para criar um aplicativo basedo no modelo "contador", execute:
$ flet create --template contador <nome_do_projeto>

# para criar o aplicativo a partir do modelo, no diretório atual, execute:
$ flet criar --template contador .

O Flet criará o diretório <nome_do_projeto> contendo o arquivo main.py:

import flet as ft

def main(page: ft.Page):
    page.add(ft.SafeArea(ft.Text("Hello, Flet!")))

ft.app(main)

No corpo da função main() podemos adicionar elementos de UI (controles) e código a ser executado. O código termina com a função ft.app(main) que inicializa o aplicativo Flet e executa main().

Rodando o Aplicativo

Rodando no destop: Para rodar o aplicativo no desktop basta executar:

# roda main.py no diretório atual
$ flet run
# esse comando executará main.py localizado no diretório atual

# se for necessário especificar um caminho diferente:
$ flet run [script]
# que executará main.py no diretório especificado

# para executar main.py em um diretório que não o atual, pode ser fornecido o caminho completo, absoluto ou relativo, para o diretório
# onde está o arquivo main.py. Por exemplo:
$ flet run /Users/Usuario/Projetos/flet-app

# o arquivo principal não preisa ser main.py:
$ flet run contador.py

Em qualquer dos casos o aplicativo será iniciado em janela nativa do sistema operacional usado.

Rodando no navegador: Para rodar um aplicativo como app da web (no navegador, portanto) usamos o comando:

$ flet run --web [script]
# uma nova janela (ou aba) será aberta no navegador, usando uma porta aleatória.

# para selecionar uma porta específica use a opção  --port (-p). Por ex.:
$ flet run --web --port 8000 app.py

Recarregamento automático: Por default o Flet carregará e rodará o arquivo principal, carregando novamente sempre que esse arquivo for alterado e gravado. No entanto a aplicativo em execução não será afetado por alterações em outros arquivos no projeto. Para que todos os arquivos sejam recarregados quando alterados usamos:

$ poetry run flet run -d [script]

# para que sub-diretórios sejam incluídos recursivamente use:
$ poetry run flet run -d -r [script]

Sintaxe do comando run

O comando run é usado para executar aplicativos do Flet e tem a seguinte sintaxe:

flet run [-h] [-v] [-p PORT] [--host HOST] [--name APP_NAME]
         [-m] [-d] [-r] [-n] [-w][--ios] [--android] [-a ASSETS_DIR]
         [--ignore-dirs IGNORE_DIRS] [script]

script é um argumento posicional, servindo para designar o caminho do script Python.

As demais opções estão listadas na tabela abaixo.

Argumento Significado
-h, --help mostra essa mensagem de ajuda e termina
-v, --verbose -v para saída detalhada e -vv para mais detalhes
-p PORT, --port PORT Porta TCP personalizada para execução do aplicativo
--host HOST host para execução do aplicativo web. Use “*” para escutar em todos os IPs.
--name APP_NAME nome do aplicativo para distingui-lo de outros apps na mesma porta
-m, --module trata o script como um caminho de módulo python, e não como caminho de arquivo
-d, --directory observar o diretório de script
-r, --recursive observar diretório e subdiretórios de script recursivamente
-n, --hidden manter a janela do aplicativo oculta na inicialização
-w, --web abrir aplicativo em um navegador da web
--ios abrir aplicativo em dispositivo iOS
--android abrir aplicativo no dispositivo Android
-a ASSETS_DIR, --assets ASSETS_DIR caminho para o diretório de assets
--ignore-dirs IGNORE_DIRS diretórios ignorados durante a observação. Para mais de um, separe com vírgulas.

Notas: † Observar, nesse caso, é estar ciente de que houve alterações no código usado para recarregamento automático, descrito acima.

Inserindo Widgets

Para obter alguma funcionalidade em nosso aplicativo temos que inserir nele controles, também chamados de widgets. Controles são inseridas na Page, o widget de nível mais alto, ou aninhados dentro de outros controles. Por exemplo, para inserir texto diretamente na page fazemos:

import flet as ft

def main(page=ft.Page):
    txt = ft.Text(value="Olá mundo!", color="blue")
    page.controls.append(txt)
    page.update()

ft.app(target=main)


Widgets são objetos do python com uma representação visual, com características controladas por seus parâmetros. value e color são parâmetros que recebem strings, esse último declarado no formato de cor do HTML. São válidas as cores, por exemplo: navyblue, #ff0000 (vermelho), etc. O objeto page possui uma lista controls, à qual adicionamos o elemento txt.

No código seguinte usamos um atalho: page.add(t) significa o mesmo que page.controls.append(t) seguido de page.update(). Também importamos o módulo time para provocar uma pausa na execução do código em time.sleep(1).

import flet as ft
import time

def main(page=ft.Page):
    t = ft.Text()
    page.add(t)
    cidades = ["Belo Horizonte","Curitiba","São Paulo","Salvador","** fim **"]
    for i in range(5):
        t.value = cidades[i]
        page.update()
        time.sleep(1)

ft.app(target=main)

Ao ser executado as quatro cidades armazenadas na lista cidades são exibidas e o loop é terminado com a exibição de ** fim **.


Alguns controles, como Row e Line são containers, podendo conter dentro deles outros widgets, da mesma forma que Page. Por exemplo, inicializamos abaixo uma linha (um objeto ft.Row) contendo três outros objetos que são strings, e a inserimos em page.

import flet as ft
import time

def main(page=ft.Page):
    linha = ft.Row(controls=[ft.Text("Estas são"), ft.Text("cidades"), ft.Text("brasileiras")])
    page.add(linha)
    t = ft.Text()
    page.add(t) # it's a shortcut for page.controls.append(t) and then page.update()
    cidades = ["Belo Horizonte","Curitiba","São Paulo","Salvador","** fim **"]
    for i in range(5):
        t.value = cidades[i]
        page.update()
        time.sleep(1)

ft.app(target=main)

O resultado é exibido na figura 1, com a cidade sendo substituída a cada momento. A linha page.update() é necessária pois o valor do ft.Text() foi alterado.

Figura 1

Vemos que Row recebe no parâmetro controls  uma lista com 3 widgets de texto.

Claro que muitos outros controles pode ser inseridos. Com o bloco abaixo podemos inserir um campo de texto, que pode ser editado pelo usuário, e um botão.

    page.add(
        ft.Row(controls=[
            ft.TextField(label="Sua cidade"),
            ft.ElevatedButton(text="Clique aqui para inserir o nome de sua cidade!")
        ])
    )

Podemos também criar novas entradas de texto e as inserir consecutivamente em page.

import flet as ft
import time

def main(page=ft.Page):
    page.add(ft.Row(controls=[ft.Text("Estas são cidades brasileiras")]))
    cidades = ["Belo Horizonte","Curitiba","São Paulo","Salvador","** fim **"]
    for i in range(5):
        t = ft.Text()
        t.value = cidades[i]
        page.add(t)
        page.update()
        time.sleep(1)

ft.app(target=main)
Figura 2

Nesse caso não estamos substituindo o conteúdo de um objeto de texto fixo na página, e sim inserindo novas linhas (figura 2). Observe que nenhum procedimento foi designado a esse botão que, no momento, não executa nenhuma tarefa.

O comando page.update(), que pode estar embutido em page.add(), envia para a página renderizada apenas as alterações feitas desde sua última execução.

Observe que o argumento controls, aqui usado em Row é um argumento posicional noemado. O nome pode ser omitido se o argumento aparecer no primreiro lugar. Ou seja:

# a linha
ft.Row(controls=[ft.Text("Estas são cidades brasileiras")])
# pode ser escrita como
ft.Row([ft.Text("Estas são cidades brasileiras")])

# se outros argumentos estão presentes, controls deve aparecer primeiro
page.add(ft.Row([ft.Text("Estas são cidades brasileiras")], wrap=True))           # certo!
page.add(ft.Row(wrap=True, [ft.Text("Estas são cidades brasileiras")]))           # erro!
page.add(ft.Row(wrap=True, controls=[ft.Text("Estas são cidades brasileiras")]))  # certo!


Para incluir alguma ação útil em nosso projeto usamos a capacidade de alguns controles de lidar com eventos (os chamados event handlers). Botões podem executar tarefas quando são clicados usando o evento on_click.

import flet as ft
def main(page: ft.Page):
    def button_clicked(e):
        page.add(ft.Text("Clicou"))
        
    page.add(ft.ElevatedButton(text="Clica aqui", on_click=button_clicked))

ft.app(target=main)

Esse código associa a função button_clicked() com o evento on_click do botão. A cada clique um novo elemento de texto é colocado na página.

Várias outras propriedades podem ser usadas para alterar a aparência dos controles. Vamos usar width (largura) no código abaixo, além do controle Checkbox, uma caixa de texto que pode ser marcada. A função entrar_tarefa() verifica se há conteúdo em nova_tarefa, um TextField e, se houver, cria e insere na página uma nova Checkbox.
Depois limpa o valor de nova_tarefa. O comando nova_tarefa.focus() coloca no comando de texto o foco da ação dentro da página, independente de ela ter ou não sido usada no if.

import flet as ft

def main(page):
    def entrar_tarefa(e):
        if nova_tarefa.value:
            page.add(ft.Checkbox(label=nova_tarefa.value))
            nova_tarefa.value = ""            
        nova_tarefa.focus()

    nova_tarefa = ft.TextField(hint_text="Digite sua nova tarefa...", width=400)
    page.add(ft.Row([nova_tarefa, ft.ElevatedButton("Inserir tarefa", on_click=entrar_tarefa, width=300)]))
    nova_tarefa.focus()

ft.app(target=main)

É claro que muitas outras ações podem ser inseridas nesse pequeno programa, tal como testar se uma entrada já existe, eliminar espaços em branco desnecessários ou gravar as tarefas em um banco de dados.

Exemplo: Controles e propriedades

É comum os tutoriais do Flet apresentarem um pequeno bloco ilustrativo de código com a operação de somar e subtrair uma unidade a um número em uma caixa de texto. Mostramos aqui um código um pouco mais elaborado para apresentar propriedades adicionais. Usamos page.title = "Soma e subtrai" para inserir um título na barra de tarefas (ou na aba do navegador, se o codigo for executado no modo web), as propriedades de alignment. Além disso declaramos os botões e caixas de texto separadamente e depois os inserimos nas linhas.

import flet as ft

def main(page: ft.Page):
    def operar(e):
        numero = int(txt_number.value) + int(e.control.text)
        txt_number.value = str(numero)
        txt_operacao.value = "soma"
        page.update()

    def mult(e):
        numero =int(txt_number.value) * int(e.control.text.replace("*",""))
        txt_number.value = str(numero)
        txt_operacao.value = "multiplica"
        page.update()

    page.title = "Soma, subtrai, multiplica"
    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)
    txt_info = ft.Text("Você pode somar ou subtrair 1 ou 10, multiplicar por 2, 3, 5, 7")
    txt_operacao = ft.TextField(value="", text_align=ft.TextAlign.RIGHT, width=100)
    
    bt1 = ft.ElevatedButton("-10", on_click=operar, width=100)
    bt2 = ft.ElevatedButton("-1", on_click=operar, width=100)
    bt3 = ft.ElevatedButton("+1", on_click=operar, width=100)
    bt4 = ft.ElevatedButton("+10", on_click=operar, width=100)    

    bt5 = ft.ElevatedButton("*2", on_click=mult, width=100)
    bt6 = ft.ElevatedButton("*3", on_click=mult, width=100)
    bt7 = ft.ElevatedButton("*5", on_click=mult, width=100)
    bt8 = ft.ElevatedButton("*7", on_click=mult, width=100)

    page.add(ft.Row([txt_info], alignment=ft.MainAxisAlignment.CENTER))
    page.add(ft.Row([bt1, bt2, txt_number, bt3, bt4], alignment=ft.MainAxisAlignment.CENTER))
    page.add(ft.Row([bt5, bt6, txt_operacao, bt7, bt8], alignment=ft.MainAxisAlignment.CENTER))

ft.app(main)

O resultado do código é mostrado na figura 3.

Figura 3

Observe que, ao se clicar nos botões de soma, por ex., o evento on_click chama a função operar(e) passando para ela o parâmetro e, que é um objeto de evento. Este objeto tem propriedades que usamos nas funções de chamada. Na soma (e subtração) capturamos e.control.text, a propriedade de texto exibida nesse botão (-1, +1, etc.). e a usamos para fazer a operação requerida. Os controles possuem diversas propriedades e respondem a eventos específicos, que devemos manipular para contruir a aparência e funcionalidade da interface gráfica.

Vale ainda mencionar que construímos as linhas com a sintaxe ft.Row([bt1, bt2, txt_number, bt3, bt4]), usando uma lista de controles previamente definidos. Essa lista está na primeira posição, onde se insere o valor do parâmetro nomeado controls. Se esse parâmetro não estiver na primeira entrada seu nome deve ser fornecido, como em: page.add(ft.Row(alignment=ft.MainAxisAlignment.CENTER, controls=[txt_info])).

Em uma questão meramente de estilo mas que pode facilitar a organização e leitura do código, podemos definir as linhas separadamente e depois inserí-las na página.

    linha1 = ft.Row([txt_info], alignment=ft.MainAxisAlignment.CENTER)
    linha2 = ft.Row(controls=[bt1, bt2, txt_number, bt3, bt4], alignment=ft.MainAxisAlignment.CENTER)
    linha3 = ft.Row(controls=[bt5, bt6, txt_operacao, bt7, bt8],
             alignment=ft.MainAxisAlignment.CENTER)

    page.add(linha1, linha2, linha3)


Python com Flet: Widgets

 

Flet: NavigationRail

NavigationRail

NavigationRail é um controle de navegação que pode ser exibido ao lado (direito ou esquerdo) de um controle principal, servindo como um menu de escolha entre algumas poucas opções.

Exemplo básico

O exemplo abaixo mostra um aplicativo com uma linha (ft.Row) contendo uma ft.NavigationRail, uma linha divisória e uma coluna com um único texto. A ft.NavigationRail, por sua vêz, contém um texto inicial, 3 controles ft.NavigationRailDestination e um texto final.

import flet as ft
def main(page: ft.Page):
    page.bgcolor=ft.Colors.GREY_400
    page.add(
        ft.Row([
            ft.NavigationRail(
                leading=ft.Text("Início"),
                destinations=[
                    ft.NavigationRailDestination(icon=ft.Icons.WOMAN, label="Mulher"),
                    ft.NavigationRailDestination(icon=ft.Icons.MAN, label="Homem"),
                    ft.NavigationRailDestination(icon=ft.Icons.CHILD_FRIENDLY, label="Criança")
                ],
                trailing=ft.Text("Final")
            ),            
            ft.VerticalDivider(width=1),
            ft.Column([ ft.Text("Texto\ndo\nAplicativo!")])],
            expand=True
        )
    )
ft.app(main)

O resultado da execução desse código está mostrado na figura 1.

Figura 1

Para fazer com que o NavigationRail apareça à direita vasta inverter a ordem de inserção dos objetos inseridos na linha ft.Row.

Propriedades de NavigationRail

Propriedade Descrição
bgcolor a cor do Container com o conteúdo do NavigationRail.
destinations define os itens de botão que são dispostos no NavigationRail. O valor é uma lista de 2 ou mais instâncias de NavigationRailDestination.
elevation o tamanho da sombra abaixo do NavigationRail. O default é 0.0.
extended Booleano com default False. Indica se NavigationRail deve ser estendido para ocupar o espaço disponível na página. No estado estendido o controle apresenta um padding lateral mais largo e os rótulos ficam ao lado dos ícones. Caso contrário esses rótulos ficam abaixo dos ícones e o container é mais estreito.

A propriadade min_extended_width é usada para definir a largura mínima do container quando estendido. No estado estendido deve-se definir label_typedeve=none.

group_alignment o alinhamento vertical para a lista de destinos dentro do container. Os controles filhos NavigationRailDestinations ficam dispostos entre os widgets postos em leading (no início da lista) e trailing (no fim da lista).

O valor deve ser um float entre -1.0 e 1.0. Os valores de group_alignment significam: -1,0: os itens serão alinhados na parte superior do espaço disponĩvel; 0.0 itens alinhados no centro; 1.0itens alinhados em baixo. Default= -1.0.

indicator_color cor dos indicadores do NavigationRail.
indicator_shape formato dos indicadores do NavigationRail. O valor é do tipo OutlinedBorder e o default é StadiumBorder().
label_type layout e o comportamento dos rótulos (labels) dentro do NavigationRail no estado default e não estendido. Os rótulos são sempre exibidos quando o controle está estendido.

O valor é do tipo NavigationRailLabelType e o default é None (nenhum rótulo é exibido).

leading um controle opcional colocado acima dos destinos no controle principal. Sua localização não é afetada por group_alignment.

O controle em leading geralmente é um FloatingActionButton, mas pode ser outro controle que não um botão, como uma imagem de um logotipo, por exemplo.

min_extended_width a largura final quando a animação estiver concluída quando se ajusta extended=True. O default é 256.
min_width a menor largura possível para o controle, independentemente dos tamanhos dos ícones ou rótulos dos destinos.

O default é 72. Este valor também define a largura mínima e a altura mínima dos destinos. Para criar um NavigationRailDestination compacto, defina min_width=56 junto com label_type=None.

selected_index índice selecionado na lista do NavigationRailDestination. Se selected_index=None nenhum destino é selecionado.
selected_label_text_style o estilo TextStyle do rótulo de um destino selecionado. Quando o destino não está selecionado o estilo em unselected_label_text_style será usado.
trailing Um controle opcional no NavigationRail, exibido abaixo dos destinos. Sua localização é afetada por group_alignment.

Pode ser usada uma lista de opções ou destinos adicionais que apenas é renderizada quando extended=True.

unselected_label_text_style o estilo TextStyle do rótulo de destino não selecionado. Quando o destino está selecionado o estilo em selected_label_text_style será usado.

Evento de NavigationRail

Evento Descrição
on_change dispara quando o destino selecionado é alterado.

NavigationRailDestination

Propriedades

Propriedades Descrição
icon ícone a exibir no destino.

# pode receber o ícone diretamente:
icon=ft.Icons.CHILD_FRIENDLY
# ou um controle flet.Icon
icon=ft.Icon(ft.Icons.CHILD_FRIENDLY)

Se selected_icon for fornecido, esse ícone só é exibido quando o destino não estiver selecionado.

icon_content idêntico à propriedade icon. Esse controle está obsoleto e será removido. Use icon.
indicator_color cor do indicator_shape (descrito abaixo) quando o destino é selecionado.
indicator_shape formato do indicador de seleção. O valor é uma instância da OutlinedBorderclasse.
label string mostrada no rótulo do destino. Só é exibida se label_content (descrito abaixo) não é fornecido.
label_content um controle usado como rótulo do destino. Se fornecido, label será ignorado.

O label deve ser fornecido no NavigationRail. Se for declarado NavigationRail.label_type=NavigationRailLabelType.NONE, o rótulo ainda é usado por questões semânticas e pode ser usado se NavigationRail.extended=True.

padding espaço interno para o item de destino. O valor é uma instância da classe Padding.
selected_icon nome do ícone ou controle alternativo exibido quando o destino é selecionado.

# usando o nome do ícone:
selected_icon=ft.Icons.BOOKMARK
# uso com controle:
selected_icon=ft.Icon(ft.Icons.BOOKMARK)

Se não for fornecido, o NavigationRail exibe icon em qualquer dos estados.

selected_icon_content ícone alternativo quando o destino é selecionado. Obsoleto, use selected_icon.

Nota: † Procure escolher ícones diferentes para estados diferentes, como ícones de traço e preenchidos para tornar o NavigationRail mais legível, como ft.Icons.CLOUD e ft.Icons.CLOUD_QUEUE. Ícones iniciais (icon) devem ser definidos para a versão com traço e selected_icon para a versão preenchida.

Exemplo de uso do NavigationRail

import flet as ft

def main(page: ft.Page):
    page.bgcolor=ft.Colors.GREY_400
    page.window.width=500
    page.window.height=400

    cidade=["Manaus", "Recife", "Olinda"]
    destinos=[
        ft.NavigationRailDestination(
            icon=ft.Icons.LOCATION_CITY,
            selected_icon=ft.Icons.AIRPLANE_TICKET,
            label=cidade[0],
        ),
        ft.NavigationRailDestination(
            icon=ft.Icon(ft.Icons.random()),
            selected_icon=ft.Icon(ft.Icons.AIRPLANE_TICKET_SHARP),
            label=cidade[1],
        ),
        ft.NavigationRailDestination(
            icon=ft.Icons.LOCATION_HISTORY_SHARP,
            selected_icon=ft.Icon(ft.Icons.AIRPLANE_TICKET_OUTLINED),
            label=cidade[2],
        ),
    ]

    def getBotao(i):
        return ft.FloatingActionButton(
            foreground_color=ft.Colors.YELLOW,
            bgcolor=ft.Colors.BLUE_300,
            icon=ft.Icons.NEW_LABEL if i==0 else ft.Icons.DELETE,
            on_click=nova_rota if i==0 else apagar,
            text="Nova Seleção" if i==0 else "Apagar Tudo",
        )

    def seleciona(e):
        texto_corpo.value+=f"\nDestino Selecionado: {cidade[e.control.selected_index]}"
        texto_corpo.update()

    def nova_rota(e):
        texto_corpo.value+=f"\n\nSelecione Nova Rota:\n{'-'*26}\n"
        texto_corpo.update()

    def apagar(e):
        texto_corpo.value=f"Selecione a sua rota:\n{'-'*26}\n"
        texto_corpo.update()

    rail = ft.NavigationRail(
        bgcolor=ft.Colors.BLUE,
        selected_index=0,
        label_type=ft.NavigationRailLabelType.ALL,
        min_width=180,
        min_extended_width=400,
        leading=getBotao(0),
        trailing=getBotao(1),
        group_alignment=0.0,
        destinations=destinos,
        on_change=seleciona,
        extended=False
    )

    texto_corpo=ft.Text(f"Selecione a sua rota:\n{'-'*26}\n", color=ft.Colors.INDIGO_900, size=16)
    espaco_direita=ft.Container(
        content=texto_corpo,
        padding = ft.padding.all(15),
        border=ft.border.all(3, ft.Colors.BLUE_600),
        alignment=ft.alignment.top_left,
        bgcolor=ft.Colors.GREY_50,
        expand=True
    )
    page.add(ft.Row([rail, ft.VerticalDivider(width=2), espaco_direita,], expand=True,))

ft.app(main)

O resultado da execução desse código está mostrado na figura 2.

Figura 2

Flet: Controles SafeArea e Placeholder

SafeArea


Outro controle voltado para a diagramação das páginas de aplicativos, SafeArea insere conteúdo com preenchimento (padding, as distâncias entre as margens internas do container com as bordas externas do controle) de modo a impedir que os elementos de interface do sistema operacional se sobreponham às do aplicativo. Ele recua o conteúdo interno evitando sobreposição pela barra de status no alto da tela.

Em particular esse recurso permite o recuo do conteúdo para evitar obstrução pelo “entalhe” no iPhone, (notch) ou outras modificações na geometria das telas em aparelhos menores. Quando um preenchimento mínimo é especificado, o maior preenchimento mínimo ou o preenchimento da área segura será aplicado.

Propriedades de SafeArea

Propriedade Descrição
bottom booleano, se o aplicativo deve evitar intrusão do sistema operacional na parte inferior da tela. Default é True.
content recebe o controle filho a ser exibido dentro SafeArea.
left booleano, se o aplicativo deve evitar intrusão do SO na parte esquerda da tela. Default é True.
maintain_bottom_view_padding booleano, default é False. Se True o controle SafeArea deve manter em exibição o MediaQueryData.viewPadding no parte inferior da tela, em vez do MediaQueryData.padding (que é o default).

Por exemplo, caso um teclado na tela seja exibido acima da SafeArea, o preenchimento interno (padding) pode ser mantido abaixo da obstrução sem ser ocultado. Pode ser útil quando o layout contém controles flexíveis que podem ser movidos na interface do usuário. Definir SafeArea=True evita alteração na IU.

minimum preenchimento (padding) mínimo a ser aplicado.
right booleano, se o aplicativo deve evitar intrusão do SO na parte direita da tela. Default é True.
right booleano, se o aplicativo deve evitar intrusão do SO na parte superior da tela, que em geral contém uma barra de status. Default é True.

Um exemplo de uso do controle pode ser visto em Uso de SafeArea.

Placeholder

A palavra “placeholder” pode ser descrita em português como “marcador de posição” ou “espaço reservado”. O controle placeholder desenha uma caixa na página, representando o local onde outro widget será colocado, mais tarde. Ele é útil para marcar áreas do aplicativo durante o desenvolvimento, para efeito de visualização e organização do projeto.

Basicamente o Placeholder pode inserido na página sem muitas propriedades.

import flet as ft
def main(page: ft.Page):
    page.add(ft.Placeholder(expand=True))
ft.app(main)

Propriedades de Placeholder

Propriedade Descrição
content um controle que pode ser adicionado dentro do placeholder (opcional)
color a cor do traço marcando o espaço reservado
fallback_height altura da caixa a ser usada quando o placeholder não tem uma altura definida. O valor é um float com default de 400.0.
fallback_width largura da caixa a ser usada quando o placeholder não tem uma largura definida. O valor é um float com default de 400.0.
stroke_width largura da linha usada para desenhar a caixa do placeholder na página. O value é um float com default de 2.0.

Exemplo de uso de Placeholder

import flet as ft

def main(page: ft.Page):
    page.title = "Página com um Placeholder"
    page.bgcolor=ft.Colors.BLUE_50
    page.window.width=500
    page.window.height=500
        
    page.add(
        ft.Container(
            border=ft.border.all(1, ft.Colors.BLACK),
            content=ft.Text("Um container com texto fora do placeholder", color=ft.Colors.BLACK),
            margin=ft.margin.symmetric(horizontal=1, vertical=1),
            alignment=ft.alignment.center,
            height=100,
            bgcolor=ft.Colors.GREEN_50,
        ),
        ft.Placeholder(
            expand=True,
            stroke_width=4.0,
            color=ft.Colors.DEEP_PURPLE_500,
            content=ft.Container(
                content=ft.Text("Um container com texto dentro do placeholder", color=ft.Colors.BLACK),
                alignment=ft.alignment.center,
                width=500,
                height=100,
            ),
            width=600,
        )
    )
ft.app(main)

Controle ReorderableListView

ReorderableListView

Um controle ReorderableListView é um widget container que admite controles filhos reposicionáveis. Ele cria uma lista similar à ListView com filhos que podem ser arrastados para novas posições, mostrando uma animação durante o movimento. Ele pode ser usado para abrigar listas com elementos de prioridade ajustável, como uma lista de tarefas ou de músicas.

Exemplo Básico

O controle ReorderableListView permite a construção de linhas ou colunas que podem ser arrastadas e reposicionadas, mudando de lugar com uma animação suave. No exemplo abaixo, dois desses controles são inseridos em uma página. No primeiro, declarado como uma lista horizontal (horizontal=True) são inseridos 2 elementos do tipo ft.Container. No segundo, uma lista vertical (horizontal=False, que é o default), são inseridos 2 elementos ft.ListTile.

import flet as ft

def main(page: ft.Page):
    page.add(        
        # 2 colunas dispostas horizontalmente
        ft.ReorderableListView(
            expand=True, horizontal=True,
            controls=[
                ft.Container(width=250, content=ft.Text("Festa"), alignment=ft.alignment.center, bgcolor="#228A82"),
                ft.Container(width=250, content=ft.Text("Trabalho"), alignment=ft.alignment.center, bgcolor="#8A4F22"),
            ],
        ),
        # 2 linhas dispostas verticalmente
        ft.ReorderableListView(
            controls=[
                ft.ListTile(title=ft.Text("Comprar cerveja"), bgcolor="#6C8785"),
                ft.ListTile(title=ft.Text("Tomar a cerveja"), bgcolor="#BA733C"),
            ],
        )
    )

ft.app(main)
Figura 1

O resultado desse código está mostrado na figura 1.

Os containers Festa e Trabalho podem ser movidos e realocados horizontalmente. Na parte inferior as linhas Comprar cerveja e Tomar cerveja podem ser arrastados verticalmentes e alterados em sua posição. Em um caso mais completo, os eventos de arrastar podem ser capturados (veja abaixo) para alterar propriedades do aplicativo, alterar um banco de dados ou executar qualquer outra ação desejada.

O arrasto é feito com o mouse nas marcas de abas (traços em azul). Se existirem mais controles que que o espaço disponĩvel para exibí-los, uma barra de rolagem é disponibilizada.

Observação: No atual estado do Flet (em Abril de 2025) a atualização de qualquer controle no aplicativo, como por exemplo, uma linha de texto informando sobre o estado da página, atualiza toda a página, retornando os controles ReorderableListView ao seu estado original.

Propriedades

O controle ReorderableListView possui as seguintes propriedades. Como ele pode conter diversos outros controles filhos a formatação e coleta de eventos dos filhos pode ser feita de forma independante.

Propriedade Descrição
anchor A posição relativa do deslocamento de rolagem zero. O default é 0,0.
auto_scroller_velocity_scalar A velocidade escalar por pixel sobre rolagem. Representa como a velocidade é dimensionada com a distância de rolagem. A velocidade de rolagem automática = (distância da overscroll) * velocidade escalar.
build_controls_on_demand Booleano. Se True controles são criados de forma preguiçosa/sob demanda, ou seja, somente quando se tornarem visíveis. Isso é útil quando de lida com um número grande de controles. O default é True.
cache_extent A janela de visualização (viewport) possui uma área antes e depois da área visível onde armazena em cache itens que serão tornados visíveis quando o usuário rola a página.

Itens nessa área de cache são dispostos antes de se tornarem visíveis na tela. O cache_extent define quantos pixels a área de cache inclui antes da borda inicial e depois da borda final da janela de visualização.

controls Lista de controles que serão inseridos e reordenados.
clipe_behavior O conteúdo será recortado (ou não) de acordo com esta opção. O valor é do tipo ClipBehavior e default é ClipBehavior.HARD_EDGE.
first_item_prototype Booleano. Se True as dimensões (largura e altura) definidas para o primeiro item são usadas como “protótipo” para os demais itens. O default é False.
footer Um controle a ser usado no rodapé. Esse item é não reordenável e será exibido ao final dos controles ordenáveis. O valor é do tipo Control.
header Um controle a ser usado como cabeçalho. Esse item é não reordenável e será exibido antes dos controles ordenáveis. O valor é do tipo Control.
horizontal Booleano, se os controles devem ser dispostos horizontalmente. O default é False.
item_extent Se não nulo, força os filhos a terem a extensão fornecida na direção de rolagem.

É mais eficiente especificar um item_extent do que deixar que os filhos determinem sua própria extensão pois o mecanismo de rolagem tem informação prévia da extensão dos filhos. Isso economiza trabalho, por exemplo, quando a posição de rolagem muda drasticamente.

padding Espaço de afastamento interno dos controles. O valor é do tipo Padding.

Eventos

O controle ReorderableListView responde aos seguintes eventos:

Evento Descrição
on_reorder Dispara quando um controle filho é arrastado para uma nova posicão. O aplicativo tem que ser atualizado para reordenar esses itens.
on_reorder_start Dispara quando o arrasto do controle filho é iniciado.
on_reorder_end Dispara quando termina o arrasto do controle filho.

O argumento de evento é do tipo OnReorderEvent, chamado e nos exemplos dados.

Exemplo de Uso do ReorderableListView

Um exemplo mais completo de uso do ReorderableListView está apresentado abaixo:

import flet as ft

def main(page: ft.Page):
    page.title = "Demonstração de ReorderableListView"
    page.bgcolor=ft.Colors.WHITE
    page.window.width=330
    page.window.height=620

    def move_coluna(e: ft.OnReorderEvent):
        print(f"Coluna movida da posição {e.old_index+1} para {e.new_index+1}.")

    def move_linha(e: ft.OnReorderEvent):
        print(f"Linha movida da posição {e.old_index+1} para {e.new_index+1}.")

    cor=[ft.Colors.GREEN_200, ft.Colors.GREEN_50, ft.Colors.GREEN_500, ft.Colors.GREEN]
    coluna=["A","B","C","D","E"]
    linha=["Comparar café","Tomar café","Comprar cerveja","Tomar cerveja","Dormir"]

    # Colunas dispostas horizontalmente
    lista_horizontal = ft.ReorderableListView(
        expand=True,
        horizontal=True,
        on_reorder=move_coluna,
        controls=[
            ft.Container(
                border=ft.border.all(1, ft.Colors.BLACK),
                content=ft.Text(f"{coluna[i]}", color=ft.Colors.BLACK),
                margin=ft.margin.symmetric(horizontal=1, vertical=5),
                width=60,                
                alignment=ft.alignment.center,
                bgcolor= cor[i%2],
            ) for i in range(5)
        ],
    )
    # linha_header
    linha_header=ft.Container(
        content=ft.Text("Coisas a Fazer", color=ft.Colors.WHITE),
        margin=ft.margin.symmetric(horizontal=0, vertical=5),
        padding=5,
        height=30,
        bgcolor= cor[2],
    )
    # linha_footer
    linha_footer=ft.Container(
        content=ft.Text("Fim da Página", color=ft.Colors.WHITE),
        margin=ft.margin.symmetric(horizontal=0, vertical=5),
        padding=5,
        height=30,
        bgcolor=cor[2],
    )

    # Linhas dispostas verticalmente
    lista_vertical=ft.ReorderableListView(
        expand=True,
        on_reorder=move_linha,
        header=linha_header,
        footer=linha_footer,
        controls=[
            ft.Container(
                border=ft.border.all(1, ft.Colors.BLACK),
                content=ft.Text(f"{linha[i]}", color=ft.Colors.BLACK),
                margin=ft.margin.symmetric(horizontal=1, vertical=1),
                width=330,
                height=40,
                padding=10,
                alignment=ft.alignment.center_left,
                bgcolor= cor[i%2],
            ) for i in range(5)
        ],
    )
    page.add(lista_horizontal, lista_vertical)

ft.app(main)

Após algumas operações de arrasto das linhas e colunas, as seguintes linhas são exibidas no console:

Linha movida da posição 1 para 4.
Linha movida da posição 2 para 3.
Coluna movida da posição 1 para 4.
Coluna movida da posição 2 para 3.

O resultado desse código está mostrado na figura 2 em seu estado inicial e depois dos arrastos descritos acima.

Observe que as propriedades controls de ambos os ReorderableListView, que são listas (lists ordinárias do Python), foram preenchidos com compressão de listas. Esse mecanismo está descrito em Compreensão de listas no Python e resumido abaixo:

$ lista1=[i** for i in range(10)]
$ print(lista1)
↳ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

$ lista2=[i** for i in range(10) if i%2==0]
$ print(lista2)
↳ [0, 4, 16, 36, 64]

Portanto o código preenche a lista ft.ReorderableListView.controls com 5 instâncias de ft.Container, com i=0,...,4. As propriedades internas variam com i em linha[i], definida como uma lista no início do código, e cor[i%2], que pode ser apenas cor[0] ou cor[1], de outra lista já definida.

A propriedade horizontal=True define que os controles são dispostos na horizontal.

 

 

 

 



Vivemos dentro de um Buraco Negro?

Os Antecedentes


A Teoria da Relatividade Geral (TRG) de Einstein é o instrumento teórico que nos permite decrever a estrutura do espaço e da matéria nele contida, em larga escala. Ela é basicamente uma descrição da gravitação universal, associando o conteúdo material do espaço com a sua geometria, responsável pelo movimento das galáxias e aglomerados galáticos. Na TRG o conteúdo de massa-energia em uma região do espaço-tempo deforma esse espaço.

†: A homogeneidade significa que o espaço é “igual” idependentemente de onde se observe. Isotropia significa que ele é “igual” independentemente de qual direção se observe. Essa igualdade se refere principalmente ao conteúdo de massa-energia. Embora ela não seja observada localmente (pois temos planetas, sistemas solares e galáxias) ela fica cada vez mais bem definida em escalas ultra-grandes.

§: A Constante Cosmológica, embora abandonada por Einstein que a chamou de “the biggest blunder of my life”, se tornou muito importante mais tarde, principalmente para incorporar na cosmologia a “energia escura” e os efeitos quânticos associados ao vácuo.

✠: Em outras palavras, o espaço-tempo não é estático: ele está se expandindo hoje e pode, no futuro se expandir para sempre ou voltar a se contrair de volta para a singularidade inicial. A decisão entre um ou outro destino cósmico depende da densidade de massa observada.

Logo após a publicação de seu trabalho Einstein percebeu que suas equações de campo seriam apropriadas para descrever o universo como um todo. Sob a suposição de que o universo é homogêneo e isotrópico ele encontrou uma solução para suas equações que deveriam descrever, pelo menos grosso modo, o comportamente da matéria dentro do espaço. Surpreso ele verificou que não existiam soluções estáticas para suas equações. Ele tentou, por um tempo, forçar a existência desse universo estático introduzindo um termo que denominou de “Constante Cosmológica”§, mas abandonou essas tentativas quando Hubble descobriu que as galáxias estão todas se afastando de nós, exceto algumas poucas que estão na nossa vizinhança. Voltando no tempo essas galáxias estariam cada vez mais próximas, até estarem todos aglomeradas em um ponto muito denso e quente, a chamada singularidade inicial. Juntamente com as observações a TRG gerou o Modelo Cosmológico Padrão, conhecido como o modelo do Big Bang. Ela descreve como, partindo de uma explosão inicial monumental, o universo entrou em sua fase de inflacionária, um período de tempo em que ele se expandou rapidamente, aumentou muitas vezes de tamanho. O modelo é corroborado por diversas observações, como o afastamento da galáxias, a abundância dos elementos químicos, entre outras. Mas ele também apresenta perguntas e dificuldades. Entre elas: se, de fato, o universo teve início em uma gigantesca explosão ocorrida ha 13,7 bilhões de anos, o que provocou essa explosão? Ou, como uma explosão caótica pode ter gerado um universo bem organizado, relativamente homogêneo e isotrópico?

Schwarzschild

Mais tarde , após o fim da Primeira Guerra Mundial, o físico alemão Schwarzschild encontrou uma solução para as equações de Einstein para o caso de uma concentração esférica de massa, como ocorre com as estrelas. Com essa solução foi possível prever que estrelas com muita massa podem colapsar em regiões muito pequenas e quentes que hoje denominamos buracos negros, BNs. Isso pode acontecer, por exemplo, quando o combustível nuclear se esgota em uma estrela e seu material, atraído pela força gravitacional, colapsa até que regiões de densidade muito altas sejam formadas (teoricamente densidades infinitas), o que rompe a estrutura do espaço-tempo e forma buracos negros. Além da singularidade central do BN também existe o horizonte de eventos, uma região em torno da singularidade de onde nenhum objeto, nem a luz, pode escapar. As soluções de Schwarzschild, inicialmente para estrelas sem rotação, logo foram extendidas para o caso de estrelas que giram, uma situação mais realista. Estrelas com muita massa e com rotação geram BNs rotatórios.

Simulação em computador de um buraco negro com um disco de acreção gasoso (visto de lado) girando em torno de um buraco negro. A gravidade superforte distorce a luz daquele disco de maneiras estranhas. Jeremy Schnittman/Centro de Voo Espacial Goddard da NASA.

Um pouco depois da apresentação da TRG outra teoria surgiu para revolucionar o ambiente da física, a Mecânica Quântica (MQ). Essa teoria é importante na descrição de objetos pequenos, nas escalas atômicas e nucleares, e é necessária para a explicação de muitos fenômenos observados, como a interação entre radiação e matéria e propriedades dos materiais. Ela é usada, por exemplo, para a descoberta de quais elementos existem nas estrelas, no meio interestelar, inclusive sua temperatura e movimentação. A MQ é a principal teoria por trás da eletrônica moderna.

Tanto a TRG quanto o MQ são teorias, internamente coerentes e verificadas pela experimentação e observação. Elas não são meras hipóteses. No entanto, e apesar de seu sucesso, elas não são coerentes entre si. Não existe uma teoria da gravitação quântica apesar dos muitos esforços que vêm sendo realizados nesse sentido. Apesar do estado incompleto em que se encontram as teorias no presente, existem situações onde elas devem ser aplicadas juntas. Um exemplo são os próprios buracos negros e as partículas que paricipam de sua formação. Outro está bem ilustrado na teoria de Stephen Hawking que considerou o que acontece quando um par de partículas se forma nas vizinhanças do horizonte de eventos de um buraco negro, quando uma delas pode ser absorvida pelo BN e a outras escapar para o espaço ambiente.

Equações de campo da Teoria da Relatividade Geral
Equação de Schrödinger da Mecânica Quântica

A Hipótese

Uma hipótese cosmológica interessante, apesar de altamente especulativa, surgiu no contexto das tentativas de unificação da relatividade geral com a mecânica quântica, e da exploração das implicações cosmológicas dos buracos negros. Este é o conceito de que nosso universo poderia estar dentro de um BN, de que o nosso Big Bang estaria associado à formação da singularidade existente em um universo “pai” ou de dimensão superior. A hipótese foi denominada de Cosmologia de Buracos Negros (Black Hole Cosmology), alternativamente por Cosmologia de Schwarzschild.

O conceito não foi elaborado em um momento específico nem houve um cientista que possa ser chamado de “criador” da hipótese. Pelo contrário, ele foi surgindo aos poucos e explorado por vários físicos. Uma linha do tempo pode ser listada sobre sua origem e desenvolvimento:

  • Roger Penrose e Stephen Hawking realizaram trabalhos importantes sobre os “teoremas de singularidade”, nas décadas de 1960 e 1970. Eles não fizeram referências diretas de que nosso universo poderia estar dentro de um buraco negro, mas seus trabalhos forneceram a base matemática para entender as condições extremas que poderiam existir em buracos negros e no Big Bang.
  • A ideia foi proposta e ganhou alguma atenção na década de 1970 quando físicos como John Archibald Wheeler e Bryce DeWitt estavam explorando as implicações da gravitação quântica e a natureza das singularidades. Wheeler foi um dos primeiros a considerar a possibilidade de que buracos negros poderiam ter conexões com a criação de universos.
  • Um dos proponentes mais conhecidos da hipótese foi o físico teórico Nikodem Popławski que, em 2010, publicou um artigo com a sugestão de que o Big Bang poderia ser o resultado do colapso de matéria em um buraco negro em um universo de dimensão superior. Popławski propôs que a singularidade no centro de um buraco negro poderia ser uma “ponte” para um novo universo, uma ideia que ele chamou de “cosmologia do buraco de minhoca” (wormholes).
  • Lee Smolin, em seu livro “The Life of the Cosmos” (1992), propôs a hipótese da “seleção natural cosmológica”, na qual inúmeros universos poderiam “nascer” dentro de buracos negros, com leis físicas ligeiramente diferentes. Aqueles com as condições favoráveis para a geração de um novo universo prosperariam com tais, em uma espécie de “evolução” de universos ao longo do tempo.
  • Roger Penrose e Stephen Hawking realizaram trabalhos importantes sobre os “teoremas de singularidade”, nas décadas de 1960 e 1970. Eles não fizeram referências diretas de que nosso universo poderia estar dentro de um buraco negro, mas seus trabalhos forneceram a base matemática para entender as condições extremas que poderiam existir em buracos negros e no Big Bang.
  • O conceito ganhou corpo e amplo reconhecimento com o trabalho do físico teórico Nikodem Popławski que, em 2010, publicou um artigo com a sugestão de que o Big Bang poderia ser o resultado do colapso de matéria em um buraco negro em um universo de dimensão superior. Popławski propôs que a singularidade no centro de um buraco negro poderia ser uma “ponte” para um novo universo, uma ideia que ele chamou de “cosmologia do buraco de minhoca” (wormholes).
  • À partir de 2022, o Telescópio Espacial James Webb (JWST) passou a coletar observações que exigem a reconstrução de nossas noções sobre o universo primitivo. Entre elas está a verificação de que predominam galáxias que giram em um sentido, em restrição a outro. Como discutiremos, isso reforça a hipótese de que nosso próprio universo esteja dentro de um buraco negro.

A Hipótese se fundamenta sobre os seguintes conceitos:

  • Tanto o Big Bang quanto o centro de um buraco negro são descritos como singularidades, regiões do espaço-tempo onde a densidade da matéria se torna muito elevada em volume pequeno, na medida em que se formam. As altas temperaturas, e portanto a densidade de energia ultrapassam os níveis que podem ser seguramente descritos pela física atual. Em um buraco negro, a singularidade é o ponto de densidade infinita no núcleo. No Big Bang, a singularidade representa o início do universo, com densidade e temperatura infinitas.
  • Um buraco negro é cercado por um horizonte de eventos, uma fronteira além da qual nada pode escapar, nem mesmo a luz. Alguns teóricos propõem que o Big Bang estaria associado a seu próprio “horizonte de eventos” dentro do qual o universo se expande.
  • Quando uma estrela massiva colapsa para formar um buraco negro, ela cria uma singularidade, em seu núcleo. A hipótese sugere que essa singularidade poderia não ser inativa mas, em vez disso, poderia levar à criação de um novo universo em expansão, como o nosso.
  • A física dos BNs e a cosmologia são áreas onde a TRG e a MQ entram em conflito. Essa hipótese surge no contexto das tentativas de unir essas duas teorias, sugerindo que o colapso de um buraco negro em um universo poderia gerar um novo universo com suas próprias leis físicas.

A ideia é baseada no “raio de Schwarzschild”, também chamado de “horizonte de eventos”, uma região limite além da qual nada pode escapar do buraco negro. Ne caso o horizonte de eventos do nosso Universo poderia ser equivalente ao limite de um buraco negro dentro de um “Universo pai”. Além disso cada buraco negro em nosso próprio universo poderia ser uma porta de entrada para um “Universo bebê”. Esses Universos seriam invisíveis para nós, pois estariam separados por seus próprios horizontes de eventos, tornando impossível a troca de informações entre eles. Segundo Poplawski os BNs não se tornam singularidades infinitamente densas e sim pontos de transição para novas realidades.

Com essa descrição fica claro que essa é uma hipótese fortemente especulativa, apesar de interessante. Ela nasce exatamente no setor desconhecido da interface da TRG e da MQ. Por muito tempo se apresentou a crítica de que não existem observações que sustentem diretamente essa hipótese. Teremos mais a dizer sobre isso abaixo. Além disso a complexidade matemática envolvida é grande, exatamente porque requer uma descrição da interface entre TRG e MQ, algo que ainda não foi alcançado. As singularidades são regiões do espaço-tempo onde as leis da física conhecidas não se aplicam e, portanto, não está nada claro como elas poderiam gerar um novo universo.

Cosmologia de Buraco Negro Crédito da ilustração: Perimeter Institute for Theoretical Physics

Uma nota técnica (pode ser pulada em uma primeira leitura): O físico teórico Nikodem Popławski trabalhou com teoricas alternativas para a Relatividade Geral, em particular a gravitação com torção (ou teoria de Einstein-Cartan). Ele fez contribuições para a cosmologia e à física de buracos negros, e mostrou que na teoria de Einstein-Cartan a singularidade central em um buraco negro pode ser substituída por uma “ponte de Einstein-Rosen” (um tipo de buraco de minhoca) que levaria a outro universo. A torção do espaço-tempo, prevista na teoria de Einstein-Cartan, evitaria a formação de uma singularidade clássica. As pontes de Einstein-Rosen, propostas pela primeira vez por Albert Einstein e Nathan Rosen em 1935, são também conhecidas como buracos de minhoca e são soluções teóricas para as equações da relatividade geral que sugerem a existência de “conexões” no espaço-tempo ligando duas regiões distantes do universo ou até mesmo universos diferentes, no caso de teorias de universos múltiplos.Na relatividade geral clássica, a singularidade no centro de um buraco negro é um ponto de densidade infinita onde as leis da física não podem ser aplicadas.

Nikodem Popławski

No panorama teórico da gravitação com torção o colapso gravitacional de uma estrela massiva não resultaria em uma singularidade, mas em uma região de transição para outro universo. Ao invés de uma ruptura com o próprio conceito de espaço-tempo, a inserção da torção (um conceito da teoria de Einstein-Cartan), a singularidade pode ser evitada, substituída por uma região de transição suave.Popławski explorou a ideia de que o Big Bang (a explosão que resultou em nosso universo) poderia ter resultar do colapso de matéria em um buraco negro em outro universo. Embora todos esses conceitos sejam especulativos e não comprovados pela observação, eles geraram interesse e discussão na comunidade científica. A teoria de Einstein-Cartan é matematicamente consistente mas não amplamente adotada pela comunidade que prefere se ater à relatividade geral clássica. A ausência de informações sobre o que ocorre no interio dos BNs torna difícil testar essas hipóteses.

A torção é um termo que pode ser naturalmente inserido nas equações de Einstein, sem romper com nenhuma das pressuposições normais da teoria. Ela é uma medida da assimetria na conexão do espaço-tempo e descreve como o espaço-tempo pode se “torcer” além de se curvar. Enquanto a curvatura do espaço-tempo (descrita pela TRG) associa a gravidade à distribuição de matéria e energia, a torção insere o momento angular intrínseco (spin) das partículas como fonte de deformação.

Universo Holográfico

O conceito do universo holográfico é uma hipótese que sugere que o universo pode ser entendido como um holograma. Mais especificamente ela afirma que toda a informação contida em um volume de espaço pode ser representada por um modelo registrado na fronteira desse espaço. O conceito está baseado em áreas como a teoria (que é uma hipótese) das cordas, a gravidade quântica e o princípio holográfico.

A hipótese foi proposta inicialmente por Gerard ‘t Hooft e desenvolvida mais tarde por Leonard Susskind, entre outros. Em 1997 Juan Maldacena sugeriu que um universo dotado de campo gravitacional (como ocorre no nosso) em um espaço de dimensões superiores (com dimensões acima das 4 dimenensões de nosso espaço-tempo) pode ser equivalente a uma teoria de campo quântico sem gravidade em uma superfície de dimensão inferior.

A fronteira de uma bola de 3 dimensões é a sua superfície, que possue apenas 2 dimensões.

O princípio holográfico afirma que toda a informação contida em um volume do espaço pode ser codificada em sua fronteira, tendo, portanto, uma dimensão menor que a do espaço original. Portanto, no nosso caso, apesar de parecer tridimensional (+ 1 dimensão de tempo) pode ser descrito por uma teoria física em uma superfície bidimensional. Dessa forma ele promove uma redução dimensional, importante em um contexto da física onde diversos modelos foram propostos propondo um número mais elevado de dimensões.

O princípio holográfico oferece uma abordagem promissora para unificar a mecânica quântica e a relatividade geral, dois pilares da física moderna que ainda não foram completamente integrados. Ela também tem implicações para a física dos buracos negros, sugerindo que a informação sobre a matéria que cai em um buraco negro não é perdida, mas sim codificada em sua superfície (o horizonte de eventos).

O universo holográfico é um conceito muito interessante, com consequências importantes em nosso entendimento do cosmos. No entanto ele ainda enfrenta grandes desafios conceituais e matemáticos, além de que não existem evidências diretas que a sustentem. Ele continua a ser uma área ativa de pesquisa na física teórica.

Observações Recentes

Desde que iniciou sua operação em 2022, o Telescópio Espacial James Webb (JWST, da NASA) têm coletando inúmeras observações que desafiam nossas noções sobre o Universo primitivo. Recentemente surgiram observações que sugerem o inesperado: a possibilidade de que o próprio Universo esteja dentro de um buraco negro.

Muitas observações verificaram que a maioria das galáxias distantes giram na mesma direção. Em um universo aleatório seria esperado que metade (aproximadamente) das galáxias giram em uma direção, outra metade em outra, dado um sentido arbitrário. A observação, no entanto, mostra que aproximadamente dois terços deles giram em um sentido, enquanto as demais giram no sentido oposto. A observação é surpreendente e demanda uma explicação, pois sugere que o próprio universo teve uma origem em rotação, o que favoreceria a existência de um número superior de galáxias girando nessa mesma direção.

Estrelas em rotação, se colapsadas e por conservação do momento angular, formam buracos negros em rotação. Isso seria compatível com a especulação de que universos são formados dentro dos BNs rotatórios.

Galáxias Espirais observadas pelo JWST. Galáxias circundadas em vermelho giram na mesma direção que a Via Láctea. Galáxias circundadas em azul giram na direção oposta. Crédito da Imagem: Monthly Notices of the Royal Astronomical Society, 2025.

Explicação Alternativa

As medidas da velocidade de rotação da Via Láctea começaram a ser realizadas no início do século XX. Gradualmente se compreendeu que a galáxia tem velocidade relevante, principalmente se considerarmos o seu tamanho gigantesco. É preciso lembrar que essa velocidade angular não é uniforma e as velocidades de objetos na periferia da galáxia são altos, provavelmente devido à presença da matéria escura.

A hipótese de que o Universo esteja dentro de um buraco negro é muito interessante e pode abrir caminho para novas decobertas fabulosas. No entanto existe uma explicação alternativa para os dados do JWST. Alguns pesquisadores se lembraram que a Via Láctea, nossa galáxia, está também em rotação. Já se pensou que a rotação de nossa galáxia fosse muito lenta, insuficiente para afetar as observações de objetos distante. Entretanto, a observação indica que a galáxia gira com velocidade angular significativa, de forma que, talvez, seja necessário recalibrar os instrumentos que medem distâncias no cosmos. Uma recalibração afetaria nossa compreensão de fenômenos fundamentais, como a taxa de expansão do Universo e a idade de galáxias distantes. Algumas indicações existem sugerindo que esse seja de fato o caso, tal como a verificação de que foram detectadas galáxias que parecem ser mais antigas que o próprio Universo.

Conclusões

Podemos concluir que a hipótese do Universo de Buraco Negro é uma especulação teórica que serve como um exercício intelectual para explorar as conexões entre buracos negros, singularidades e a origem do universo. O estudo desse tópico pode contribuir para a formulação de uma teoria consistente dos domínios do universo com altas densidades de matéria e energia, portanto curvaturas extremas, existam em regiões tão pequenas que exigiriam uma descrição quântica. Em outras palavras, ele poderia ajudar para o estabelecimento de uma teoria quântica da gravitação. Como uma hipótese física ela deve oferecer métodos de ser submetida ao teste da expeimentação ou observação (mais comum na astrofísica). Se passar nos testes propostos ela se torna uma teoria que, por sua vez, deve ser capaz de realizar previsões sobre o que se pode encontrar no universo.

Supondo que as descobertas do JWST realmente apontam para um padrão de rotação das galáxias suporte o conceito da Cosmologia de Buraco Negro, pode ser necessário um reajuste completo dos conceitos atuais de Cosmologia Padrão. Se buracos negros podem dar origem a novos universos seremos forçados a aceitar um modelo de universo cíclico, onde novos cosmos emergem continuamente, muito diferente do atual modelo aceito de um universo que tem uma origem bem definida, embora seu destino final não seja bem definido.

Bibliografia

Videos

Vídeos em inglês. Clique em “Closed Caption” para legendas.

Ciência Todo Dia: Nós estamos dentro de um buraco negro?

Brian Cox: Is The Whole Universe Inside a Black Hole?

PBS Space Time: Could The Universe Be Inside A Black Hole?

Space Dust: Do We Live Inside A Black Hole?

Artigos de Divulgação na Internet

 

todos as páginas visitadas em março de 2025.

Trabalhos Acadêmicos Relevantes

 

  • Nikodem Popławski: Cosmology with torsion: An alternative to cosmic inflation.
    Popławski propõe que o Big Bang pode ter sido o resultado de uma singularidade em um buraco negro em um universo de dimensão superior. Este trabalho é uma das bases teóricas para a hipótese de que nosso universo está dentro de um buraco negro.
  • Lee Smolin: The life of the cosmos.
    Smolin explora a ideia de que buracos negros podem dar origem a novos universos, uma teoria conhecida como “seleção natural cosmológica”. Embora não seja exatamente a mesma hipótese, está relacionada.
  • Roger Penrose: Cyclic Cosmology and Conformal Infinity.
    Penrose discute a possibilidade de universos cíclicos e como buracos negros podem desempenhar um papel na criação de novos universos.
  • Stephen Hawking e James Hartle: Wave Function of the Universe.
    Este trabalho clássico explora a natureza quântica do universo e como singularidades de buracos negros podem estar relacionadas à origem do cosmos.
Livros Recomendados

 

  • Leonard Susskind: The Black Hole War.
    Discute o princípio holográfico e a física de buracos negros, fundamentais para entender a hipótese de universos dentro de buracos negros.
  • Roger Penrose: Cycles of Time.
    Explora a ideia de universos cíclicos e como buracos negros podem estar conectados à criação de novos universos.
  • Michael Talbot: The Holographic Universe.
    Aborda o princípio holográfico e como ele pode ser aplicado à cosmologia, incluindo a ideia de que nosso universo poderia ser uma projeção de um buraco negro.
Conceitos relacionados

Esses tópicos estão intimamente ligados à hipótese de que nosso universo poderia estar dentro de um buraco negro:

  • Singularidades de buracos negros e o Big Bang,
  • Princípio holográfico,
  • Gravidade quântica em loop,
  • Multiverso e dimensões superiores,
  • Teoria das cordas e branas

Outros Artigos nesse Site

Devemos Acreditar na Ciência?
Teoria, Hipótese e Modelo em Física

O Céu pode cair sobre nossas cabeças?
Porque o Céu Noturno é escuro? (e por que isso é um paradoxo?)
Como se mede o afastamento da galáxias?
O Big Bang é o modelo correto do Universo?
Existem mais de um Universo?
O que é Matéria Escura?

Regex, Consulta Rápida

Segue um resumo tipo cheat sheet para referência rápida sobre o uso de Expressões Regulares no Python.

Grupos de Caracteres

Padrão casa com
\w uma palavra comsposta de caracteres a-z, A-Z, 0-9 e sublinhado (_)
\d umúnico dígito 0-9
\s um espaço em branco incluindo \t, \n e \r
. qualquer caracter exceto quebra de linha
\W qualquer sinal exceto caracter alfanumérico e sublinhado
\D qualquer caracter exceto um dígito
\S qualquer caracter exceto um espaço em branco

Âncoras

Padrão significa
^ início de uma string
$ fim de uma string
\b posição definida como limite de palavra
\B posição definida como não sendo limite de palavra

Quantificadores

Na tabela abaixo chamamos de “quantificadores gulosos” ou greedy, aqueles que englobam a maior parte de texto possível casando o padrão. Já os “quantificadores não gulosos” ou lazy, englobam a menor parte de texto que satisfaz o padrão.

Quantificadores gulosos quantificadores não gulosos casa com
* *? o elemento precedente zero ou mais vezes
+ +? o elemento precedente uma ou mais vezes
? ?? o elemento precedente zero ou uma vez
{n} {n}? o elemento precedente exatamente n vezes
{n, } {n,}? o elemento precedente pelo menos n vezes
{n, m} {n, m}? o elemento precedente de n até m vezes

Conjunto e Faixas

Chamamos de faixas as ranges ou regiões delimitadas de um certo conjunto.

Padrão casa com
[XYZ] qualquer um dos elementos X, Y ou Z
[X-Y] elementos na faixa de X até Y
[^XYZ] qualquer elemento exceto X, Y ou Z
[^X-Y] qualquer elemento exceto aqueles na faixa de X até Y

Capturando Grupos

Padrão significa
(X) Captura X como um grupo
(?P<nome>X) Captura X e atribui a ele o nome
\N Referencia o grupo capturado #N
\g<N> sintaxe alternativa para referenciar o grupo capturado #N
X | Y casa X ou Y
(X) | (Y) casa o grupo (X) ou (Y)

Retrovisores

Em inglês se usa as expressões lookaround, lookbehind e lookafter para significar a busca por padrões dadas condições antes e depois do padrão regex. Chamaremos aui essas expressões de retrovisores.

Padrão significa
X(?=Y) casa com X se seguido por Y
X(?!Y) casa com X se não for imediatamente seguido por Y
(?<=Y)X casa com X se precedido por Y
(?<!Y)X casa com X se não precedido por Y

Funções Regex

São funções do módulo re:

re.fullmatch()retorna um objeto Match se o padrão casa com a string inteira

Método retorna
re.search(padrao, texto) 1º texto casado e sua posição, em qualquer parte do texto e em todas as linhas,
re.match(padrao, texto) 1º texto casado e sua posição, no início do texto e apenas na 1ª linha,
re.findall(padrao, texto) retorna uma lista com todos os trechos encontrados,
re.finditer() retorna um iterador com todos os trechos encontrados, não superpostos
re.split(padrao, texto) parte o texto na ocorrência do padrão e retorna as partes,
re.sub(padrao, sub, texto) substitue em texto o padrao por sub,
re.subn(padrao, texto) similar à sub mas retorna tupla com nova string e número de substituições
re.compile(padrao) compila e retorna um padrão regex pre-compilado

Flags ou sinalizadores Regex

Flag alias flag inline significado
re.ASCII re.A ?m essa flag só é relevante para padrões em bytes. Ele faz com que \w, \W,\b, \B, \d, \D e \S casem com ASCII caracteres apenas, ao invés do casamento com Unicode.
re.DEBUG N/A N/A a flag re.DEBUG provoca a exibição da informação de debug para o padrão compilado.
re.IGNORECASE re.I ?i faz busca independentemente do caso (maiúsculas/minúsculas). Portanto o padrão [A-Z] casa caracteres [a-Z] ou [a-z].
re.LOCALE re.L ?L só é relevante em padrões de bytes. Faz com que \w, \W, \b, \B e casamentos sensíveis ao caso dependente do locale do computador. Essa flag não é compatível com a flag re.ASCII flag.
re.MUTILINE re.M ?m essa flag faz com que as marcações ^/$ casem texto no início/final de cada linha em texto multi-linhas.
re.DOTALL re.S ?s essa flag faz com que o ponto (.) case todos as caracteres, inclusive newline. (Por default a marcação de ponto (.) casa qualquer caracter exceto newline).
re.VERBOSE re.X ?x essa flag permite que o padrão seja organizado em seções logicas, incluido a inserção de comentários.

Bibliografia

A Ilusão da Adequação da Informação


Ilusão da Adequação da Informação

“O conflito interpessoal está piorando, gerando aumento na raiva, na ansiedade e estresse geral. Nossa intenção era a de investigar esses mal-entendidos e ver se eles poderiam ser mitigados”.
— Angus Fletcher, coautor do estudo, teórico narrativo e neurofisiologista da Ohio State University.

Um estudo demonstrou a existência de um tipo de viés cognitivo, chamado Ilusão da Adequação da Informação, que ainda não havia sido descrito. Nesse estudo, os pesquisadores reuniram três grupos de pessoas, os sujeitos do estudo, e apresentaram a eles, de forma diferenciada, informações sobre um tópico controverso. O grupo A recebeu a informação parcial, contendo apenas um dos aspectos sobre o assunto pautado e que sugeriam um curso de ação na solução do problema. O grupo B também recebeu informação parcial, com outro aspecto diferente e apontado para uma tomada de decisão diferente. Quanto ao grupo C, eles receberam toda a informação disponível sobre o tema, contendo ambos os lados da informação. Em seguida, os pesquisadores perguntaram a todos os envolvidos que posição eles adotaram em relação ao assunto controverso, e que alternativa eles adotariam para resolver o problema. Além disso, consultaram os participantes sobre se eles precisariam de alguma informação adicional antes de formar uma opinião completa sobre o assunto.

O resultado foi o seguinte: a maioria das pessoas em todos os três grupos concluiram que tinham informações completas sobre o assunto, que conheciam todos os aspectos relevantes sobre o tema. Pessoas no grupo C, que de fato haviam recebido a informação completa, ainda que estivessem corretas, estavam presumindo esse fato pois não teriam como avaliar se existiam dados além daqueles a que foram apresentados. Pessoas dos grupos A e B, que receberam informações parciais, também presumiram ter conhecimento completo sobre o tema. Essa é, exatamente, a chamada ilusão da adequação das informações.

Além dessas perguntas iniciais, os pesquisadores também perguntaram às pessoas como eles se posicionaram sobre a questão, e se julgavam que os demais membros da pesquisa concordariam com eles em um debate. Evidentemente, aqueles que acreditavam possuir todas as informações sobre o tema formaram uma opinião concreta sobre ele, além de acreditam que todas as demais pessoas deveriam concluir da mesma forma e chegar às mesmas conclusões. Claro que, no caso desse experimento, as pessoas dos três grupos haviam recebido informações diferentes e chegaram a conclusões diversas. E, debatendo o assunto, essas pessoas não conseguiram alcançar uma visão comum de consenso.

Nota †: Nesse aspecto o viés de cognição descrito tem uma semelhança com o chamado Efeito Dunning-Krueger.

O grupo C, que recebeu informações sobres os dois lados da questão, teve uma reação diferente, uma posição mais comedida e, portanto, menos confiante. Elas construíram uma certeza menor sobre o tema em questão. Essas pessoas tinham um conhecimento maior sobre o tópico discutido e sabiam que existia mais de um lado para o assunto. Assim sendo, não seria estranho que eles suspeitassem de que novas visões poderiam ser apresentadas, o que torna mais difícil a tomada de uma posição definitiva. Essa pessoas apresentaram níveis de incerteza maior, enquanto as pessoas dos grupos A e B tinham total certeza de que apenas a sua própria conclusão faria qualquer sentido.

O artigo original pode ser encontrado em PLOS One, Hunter Gehlbach, Carly D. Robinson, Angus Fletcher, no link The illusion of information adequacy.

Consequências

Embora ainda não tenham surgido estudos completos sobre esse tema, não é difícil especular que o resultado desse experimento tem consequências importantes na compreensão do estado de radicalização e polarização dos dias modernos. A formação de bolhas na vida das redes sociais garante que as informações circulem de forma parcial, sendo extremamente difícil furar a bolha. Esses núcleos de divulgação de informações (verdadeiras ou não) alcançam limites muito além daqueles que vemos na vida social comum, não eletrônica. Relatos anedóticos, interpretações incorretas e até mesmo a falsidade deliberada para alcançar fins pessoais, econônimos ou políticos são espalhados e amplificados pela repercução nas mídias. O viés cognitivo que denominamos a ilusão de adequação da informação encontra terreno fértil para selecionar e espalhar informações que corroboram a crença comum do grupo. A necessidade individual por aceitação e apreço dos “amigos”, reais ou virtuais, completam o esquema. Junta-se a isso a influiência conjunta da maiorias dos outros viéses de cognição, como os descritos nos artigos Viéses de Cognição e Bonhoeffer, Comportamento Heurístico e Viéses de Cognição , nesse site.

Posicionamentos radicalizados dentro das bolhas levam os grupos a formarem opiniões e tomarem decisões baseados na informação parcial a que têm acesso, se unam contra indivíduos de posição diferentes, circulem entre si suas “verdades absolutas” e se radicalizem cada vez mais. As redes sociais se encarregam de servir de ambiente para essa divulgação e para insuflar o ódio, essencial para que seus usuários aumentem sua participação nas redes e passem nelas maior tempo.

“Quanto menos nosso cérebro sabe, mais confiante ele se torna de que sabe tudo o que precisa saber. Isso nos torna propensos a pensar que temos todos os fatos cruciais sobre uma decisão, pulando para conclusões confiantes e julgamentos decisivos, quando estamos perdendo as informações necessárias.”
— Fletcher, um dos autores do artigo

Consequências tecnológicas podem resultar desse estudo. A pesquisa mencionada não foi direcionada para aplicações tecnológicas, da interação entre máquina e usuário, nem em questões da segurança cibernética. Ela precisa ser complementada por experimentos adicionais, na busca de verificação do mesmo viés em áreas diversas da cognição. O gerencimento da informação, mecanismos de buscas e outros podem ser severamente afetados pela insuficiência cognitiva. De fato, qualquer dificuldade humana na tomada de decisões pode levar a vulnerabilidades e desafios legais, especialmente quando a tecnologia da informação está envolvida. O reconhecimento desse viés deve levar a investigações mais completas para analisar essas ameaças. As descobertas ressaltam a importância da “humildade da informação” e sugerem uma reavaliação das práticas de tomada de decisão onde dados são considerados críticos.

Narrativas


O médico neurologista Steven Novella, no Podcast The skeptics Guide to the Universe, Episódio #1007, apontou com bastante propriedade que qualquer relato feito por um indivíduo é sempre uma narrativa. Diferente do uso que vem se consolidando nos últimos tempos, especialmente no ambiente político brasileiro, uma narrativa não é um relato necessariamente falso ou forjado. Pelo contrário, ele é a exposição de uma experiência ou aprendizado que contém os viéses de cognição embutidos na pessoa que relata. É impossível que se alcance um nível de imparcialidade tal que a narrativa seja equivalente a “um relato completamente fidedigno do ocorrido ou existente”.

Nota ‡: Considerando nossa deficiência na captação de qualquer fenômemo por causa de nossas limitações sensórias, de interpretação e de memória, seria importante lembrar que:

  • não podemos confiar totalmente em nossa percepção sensorial;
  • não podemos confiar na interpretação que damos a algo percebido;
  • não podemos confiar na memória que retemos da experiência.

Narrativas são as histórias que as pessoas contam, oralmente ou gravadas por qualquer tecnologia, e estão coloridas por várias camadas de deformação. Ao ouvir (ou ler) um relato não podemos baixar a guarda do pensamento crítico em nenhum momento. Pessoas que apreenderam apenas um lado do relato terão sempre certeza de suas conclusões que, com quase toda a certeza, serão parciais quando não completamente errôneas. Para tornar mais complexa a nossa dificuldade em entender, não é demais lembrar que coisas e eventos do mundo real são multifacetadas. Quando lemos um livro ou assistimos a um documentário estamos nos informando sobre o ponto de vista de quem produziu o conteúdo. Essa será sempre uma narrativa. Claro que isso não significa dizer que todos os relatos, livros ou documentários possuem o mesmo grau de autoridade, ou de falsidade. Parece razoável afirmar que existem relatos mais completos e realistas, principalmente aqueles realizados por especialistas ou alguém que teve experiência direta do evento. Contra essa última afirmação trabalha a desconfiança com que muitas pessas hoje encaram a autoridade, principalmente acadêmica.

Mesmo que conheçamos um assunto em profundidade não é possível afirmar que temos todos os dados relevantes sobre aquilo. Em particular devemos estar alertas, e desconfiados, contra narrativas limpas e exatas, que não contemplam a dissenção e a possibilidade de erro. Pacotes de informações muito claros e unilaterais tendem a ser enganosos.

Alguns exemplos podem ilustrar o viés da ilusão da adequação.

Exemplos

Exemplo 1: O biólogo marinho inglês Alister Hardy, em 1960, propôs a hipótese do macaco aquático, sugerindo de que antepassados humanos divergiram da linha evolutiva dos demais grandes macacos, adotando hábitos aquáticos e vivendo por um período dentro d’água. A hipótese foi sugerida antes que as principais descobertas de fósseis de hominídeos fossem feitas na África Oriental, e argumentava que, impelidos pela competição com outras espécies, um ramo de macacos foi forçado a buscar alimentos no fundo do mar, se adaptando a características próximas as dos mamíferos aquáticos. Isso explicaria a ausência de pelos e bipedalismo nos humanos modernos. Elaine Morgan, uma escritora de divulgação científica, autora de vários livros sobre antropologia e evolução, defendeu essa hipótese em seus textos. Seu livro The Descent of Woman, publicado em 1972, foi um best-seller internacional e se tornou muito popular entre os leigos.

Qual é o nível de certeza que você tem sobre as coisas em que acredita? Você já parou para considerar quais são os fatores que te levaram a formar uma determinada opinião, ou adotar uma crença? Suas opiniões e crenças são baseadas em alguma consideração e estudo, ou são adotadas por instinto, ou apenas porque elas são a cultura de seu ambiente social e de sua família?

Apesar do apelo à mentalidade não treinada popular, os antropólogos nunca levaram a hipótese a sério, principalmente porque ela não é consistente com o registro fóssil. Em outras palavras, não existem evidências para dar suporte à hipótese. Entre outras coisas, as características humanas que ela tentava explicar evoluíram em épocas muito diferentes, o que não seria compatível com um único período aquático. Embora a hipótese do macaco aquático tenha sido fartamente desmascarada pela comunidade científica, sendo classificada como pseudociência, ela alcançou grande apelo popular desde a publicação de “Descent of Woman”. Morgan recebeu diversos prêmios e honrarias, e o leitor não cientista acredita que ela era uma cientista extraordinária e que foi a propositora da hipótese. Para complicar, as pessoas passaram a julgar que a recusa da comunidade científica em aceitar o conceito de macaco aquático estava baseada em ciúmes e conservadorismo, o que a impediu de avaliar corretamente a sugestão.

Eratostenes e a medida do raio da Terra

Exemplo 2: Outro exemplo interessante e mais conhecido é a afirmação de que a Terra é plana, já tratada nesse site no artigo Porque existem Terraplanistas. Baseados em leituras questionáveis do texto bíblico e nas medidas de Samuel Rowbotham, no século 19, um número extraordinariamente grande de pessoas passou a defender o conceito de que a descrição de um planeta esférico faz parte de uma conspiração global, talvez organizada pela NASA. Eles afirmam que a Terra é plana, que o Sol e Lua são “lanternas” que não se encontram muito longe do solo, que as estrelas são pequenos pontos brilhantes na abóbada celeste, e que a gravitação não existe. Eles preferem ignorar as inúmeras evidências que comprovam a esfericidade, inclusive a medida do raio da Terra feita pelo grego Eratostenes (276 A.C. – 194 A.C.). Ocasionalmente um terraplanista realiza uma medida que claramente demostra o erro de sua hipótese (embora poucos se deixem convencer por essa verificação).

O “terraplanismo” contém inúmeros apelos à mentalidade capturada e ignorantes dos viéses de cognição. Primeiro observamos o realismo ingênuo (melhor descrito abaixo). Quem olha do alto de uma montanha, ou do centro de uma grande planície verá uma extensa planície. A Terra parece plana por ser uma esfera enorme. Em segundo lugar, de posse de poucas informações, muitas delas errôneas, a pessoa adota uma crença forte, sustentada pela aprovação de seu grupo, e pela suposta “nobreza” de estar contra a maioria. Segue-se a completa descofiança que essas pessoas têm pela autoridade científica e acadêmica.

Terra Plana

Metacognição

Metacognição significa refletir sobre nossos próprios pensamentos, opiniões e crenças, usando introspecção. A avaliação constante de tudo o que foi construído no edifício do conhecimento é uma tarefa básica do método científico. A história mostra que abandonar conceitos arraigados e bem estabelecidos, em uma determinada época, é extremamente difícil. No entanto, o acúmulo de novas evidências apresentadas pela experimentação e observação termina por derrotar as barreiras do conservadorismo do pensamento. Não raro é necessário esperar que toda uma geração de pensadores e cientistas seja substituída para que novas mentes consigam assimilar e utilizar a inovação. No entanto, como indivíduos, podemos nos beneficiar do processo de metacognição, da introspeção sobre o estado de nossa consciência e das processos que usamos para agregar e processar novas informações. É útil conhecer, e saber identificar em nós, os processos de formação dos viéses de cognição e outras distorções da percepção humana. É vital saber que nossos cérebros, embora uma ferramenta poderosa e versátil, não é infalível. Ajuda compreender que os processos evolutivos não favoreceram cérebros que questionam e desejam conhecer melhor os processos da natureza e dos humanos.

Realismo Ingênuo

Toda a percepção é inerentemente subjetiva. O objeto percebido estará sempre colorido pelo ambiente subjetivo e cultural, racional ou não, do observador. Essa descoberta apoia a sugestão de somos guiados pelo “realismo ingênuo”, a crença de que a compreensão subjetiva de uma situação por um indivíduo é a verdade objetiva. Os estudos sobre o realismo ingênuo geralmente se concentram na forma como as pessoas podem ter compreensões muito diferentes em face da mesma situação. A ilusão de adequação da informação, por outro lado, mostra como as pessoas podem desenvolver compreensão totalmente diferente sobre um tema, se ambas estiverem expostas a informações parciais e insuficientes.

A tendência humana de acreditar que a informação obtida por meio dos órgãos sensoriais está imediatamente completa, e fornece uma descrição fidedigna do objeto percebido, é um viés muito básico que permeia praticamente todos os demais vieses de cognição. Esse é chamado, em psicologia, de Realismo Ingênuo, baseado no conceito filosófico e epistemológico de mesmo nome. Essa falha cognitiva leva as pessoas a acreditarem que todos os que discordam delas devem ser desinformadas, irracionais ou tendenciosas. O termo foi cunhado pelo psicólogo social Lee Ross e seus colegas na década de 1990, e está relacionado ao conceito filosófico de realismo ingênuo, uma forma de empirismo puro que sustenta que a percepção sensorial permite a obtenção direta de conhecimento dos objetos, sem a intermediação de processamento racional.

Através dos experimentos e observações, os psicólogos sociais propuseram que toda a percepção é inerentemente subjetiva. O objeto percebido estará sempre colorido pelo ambiente subjetivo e cultural, racional ou não, do observador. Nesse caso a palavra “ingênuo” não deve ser tomada como indicadora de tolice ou estupidez. Pelo contrário, é natural que se adote essa postura até que a instrospecção e a experimentação altere a nossa percepção de nós mesmos e do mundo.

Para descrever o efeito os psicólogos sociais propuseram três princípios básicos que alimentam o realismo ingênuo. De acordo esse modelo, as pessoas:

  • acreditam que sua percepção sensorial é uma visão clara e objetiva, sem preconceitos ou deformações;
  • esperam que todas as outras pessoas cheguem às mesmas conclusões se expostas às mesmas informações, se as interpretarem de modo racional.
  • supõem que os que não atingiram as mesmas conclusões são necessariamente ignorantes, irracionais ou tendenciosos.

Uma descrição um pouco mais completa do estudo realizado está apresentada abaixo.

O Estudo

No estudo, a equipe da Ohio State, da Universidade Stanford e da Universidade Johns Hopkins realizou uma entrevista online com 1.261 estadunidenses. Todos os participantes leram um artigo sobre uma escola fictícia onde o abastecimento de água era inadequado. O grupo A leu um artigo que continha a sustentação de que a escola deveria se fundir com outra escola, para garantir melhor fornecimento de água. O grupo B leu um artigo contendo argumentos sustentando que as escolas permanecessem separadas, enquanto se aguardava outras soluções para o problema. O grupo C era o grupo de controle, onde as pessoas tomaram conhecimento de argumentos pró e contra a fusão das escolas.

Eles descobriram que a maioria dos dois grupos que leram apenas os argumentos parciais, pró-fusão ou anti-fusão, acreditavam que tinham informações suficientes para tomar uma boa decisão sobre o que fazer. A maioria afirmou estar pronta para seguir as recomendações do artigo que leram. Aqueles que leram o artigo “pró-fusão” foram significativamente mais propensos a recomendar que as escolas se fundissem, enquanto os participantes “pró-separação” foram propensos a recomendar que as escolas permanecessem separadas. Cerca de 55% do grupo de controle recomendou a fusão das escolas.

Os participantes que tinham metade das informações também disseram que estavam convictos de que a maioria das outras pessoas tomaria a mesma decisão que eles. O grupo de investigadores chamou essa crença, de que estamos corretos mesmo na ausência de informações completas, de ilusão da adequação.

Terra Plana

Bibliografia

 

Bonhoeffer, Comportamento Heurístico e Viéses de Cognição

A estupidez é um inimigo mais perigoso do que a maldade. Pode-se protestar contra o mal; ele pode ser exposto e, se necessário, evitado pelo uso da força. O mal sempre carrega consigo o germe de sua própria subversão, deixando pelo menos um sentimento de inquietação nas pessoas. Contra a estupidez, somos indefesos. Nem protestos nem o uso da força conseguem algo aqui; a razão cai em ouvidos surdos; fatos que contradizem o prejulgamento simplesmente não são considerados e a pessoa estúpida passa a criticar até os fatos irrefutáveis. A pessoa estúpida, ao contrário da pessoa má, está satisfeita consigo mesma. Irritável, ela se torna perigosa e pode partir para o ataque. Por isso é preciso ter uma precaução maior com o estúpido do que com o mal. Tentar persuadir a pessoa estúpida por meio da razão é insensato e perigoso.
— Dietrich Bonhoeffer (1906-1945)
Dietrich Bonhoeffer

Dietrich Bonhoeffer foi um teólogo, pastor e um membro importante da resistência contra o nazismo na Alemanha de Hitler. Além de seus textos sobre teologia, ele ficou conhecido por sua resistência contra a ditadura nazista, ao programa de eutanásia de Adolf Hitler e perseguição aos judeus, ciganos, comunistas e outros grupos. Bonhoeffer testemunhou a ascenção de ideias malignas, propostas pelo regime nazista, e como elas foram aceitas de forma estúpida pela sociedade alemã, que estava pouco interessada nos destino daqueles que foram prejudicados pelo regime. Ele foi preso em abril de 1943 pela Gestapo, mais tarde acusado de ter participado de um complô para assassinar Hitler. Julgado com outros conspiradores ele foi enforcado em 9 de abril de 1945, quando o regime nazista começava a colapsar. Muito do que Dietrich Bonhoeffer propôs para explicar e combater o alto nível de intolerância e obscutantismo dos alemães que deram sustentação ao regime autoritário nazista é útil para entender o que está acontecendo no campo cultural, social e político no mundo inteiro, inclusive no Brasil.

Segundo Bonhoeffer, estupidez é diferente da canalhice e da maldade. Ela não é uma falha no caráter, nem uma suspensão momentânea da razão. Pelo contrário, ela é uma parte da psicologia bem definida, construída progressivamente por meio do acesso deficiente à informação de qualidade, e estimulada pelo funcionamento heurístico da mente humana. O estúpido atribui veracidade à ideia mais inverossímil, à conspiração mais ridícula e à proclamação mais perigosa. E esse fenômeno é frequentemente visto nas redes sociais. O grande problema está em que vozes irracionais são contagiosas, viralizam e se espalham na sociedade que, eventualmente e com algum atraso, descobre com perplexidade como a ignorância é mais ameaçadora do que a própria maldade.


 

O que é Comportamento Heurístico

“Comportamento heurístico da mente humana” é a expressão usada para se referir ao uso de atalhos mentais usados pelos indivíduos na tomada de decisões rápidas , para a solução de problemas de modo eficiente. Esse comportamento faz parte da mente e cognição humanos normais, frequentemente empregados na solução de situações complexas, ou dadas informações incompletas, que exigem resposta imediata. Embora eles sejam eficazes para reduzir a carga cognitiva, liberando recursos mentais, eles também podem levar a vieses cognitivos e erros graves de julgamento.

Herbert A. Simon

O economista e psicólogo cognitivo Herbert A. Simon foi o responsável pela introdução do conceito de heurística, na década de 1950. Ele sugeriu que a racionalidade usada na tomada de decisões pode ser muito limitada, por diversos fatores. Na década de 1970, os psicólogos Amos Tversky e Daniel Kahneman ampliaram esse campo de estudo com suas pesquisas sobre viéses de cognição, introduzindo os modelos heurísticos específicos, uma área de estudos que vem sendo ampliada até hoje. Enquanto alguns argumentam que a preguiça pura está por trás do processo heurístico, isso poderia ser apenas uma explicação simplificada para o motivo pelo qual as pessoas não agem da maneira que esperávamos.

São alguns tipos comuns de heurísticas:

  • Heurística de disponibilidade, que consiste em fazer julgamentos baseados em exemplos vêm à mente com maior facilidade. Por exemplo, as pessoas tendem a superestimar o risco de acidentes com aviões porque tais eventos são impressionates, ficam gravados na memória e são fáceis de lembrar.
  • Heurística representativa, que leva as pessoas a julgar a probabilidade de um evento tomando como base a semelhança que eles têm com outros eventos populares e estereotipados. Por exemplo, existe a tendência a julgar que senhoras idosas usando um tom de voz tranquilizador são necessariamente confiáveis e bondosas, embora a aparência não seja uma base de julgamento.
  • Heurística de ancoragem e ajuste, se refere à tendência das pessoas de confiar mais na primeira informação (a “âncora”) a que têm acesso. Por exemplo, em uma negociação para a compra de um produto, o lance inicial pode fixar pelo menos a faixa aceitável de preços. Esse viés pode tornar mais difícil a consideração de fatores adicionais inseridos posteriormente, nos levando a fazer más escolhas. Outro exemplo é a opinião formada por um visitante a um bairro que ele desconhece, se logo na chegada ele assiste a um evento violento e desagradável que pode ser associado à normalidade daquela região.
  • Heurística da escassez, que nos faz enxergar como mais valiosas as coisas mais escassas ou menos disponíveis. Profissionais de marketing usam com frequência essa heurística para influenciar as pessoas a comprar produtos. (“Oferta por tempo limitado” ou “enquanto durar o estoque”).
  • Heurística da tentativa e erro, que leva as pessoas a usarem diferentes estratégias para resolver um problemas, até que encontrem algo que funciona. Por exemplo, as pessoas usam tentativa e erro para jogar videogames, encontrar a rota de carro mais rápida para o trabalho ou para aprender uma nova habilidade. Evidentemente, tentativa e erro pode ser necessária em alguma situação mas, muitas vezes, um pouco de estudo e programação resolveriam o problema com mais eficiência.

Essas heurísticas são úteis em muitas situações, e são um mecanismo normal e válido do cérebro. Mas também podem levar a erros e vieses sistemáticos, o que mostra a importância de entendermos esses atalhos mentais para evitar o erro causado por eles na tomada de decisão.

Uma grande parte da necessidade da escolha baseada em heurística está assentada sobre a incrível dificuldade que o cérebro humano tem para lidar com fenônemos probabilísticos. Tversky e Kahneman reuniram pessoas para a realização de um teste, e deram a eles a seguinte descrição de “Linda”:

“Linda tem 31 anos, é solteira, franca e muito inteligente. Ela é formada em filosofia e, em seus tempos de estudante, sempre esteve profundamente envolvida com questões de discriminação e justiça social. Ela também participou de manifestações antinucleares”. Em seguida os participantes tinham que marcar qual era a declaração mais provável, em um conjunto de pares de afirmações. Entre as declarações estava esta:

A- “Linda trabalha como caixa em um banco”, e
B- “Linda trabalha como caixa em um banco e é muito ativa no movimento feminista”.

O que se verificou entre os entrevistados foi uma forte tendência para escolher B como a afirmação mais provável, por ela parecer mais descritiva do personagem Linda. No entanto, o conjunto descrito em B é um subconjunto de A, e não pode ser mais provável que ele. Em outras palavras: todos os caixas de banco que são feministas (B) são caixas de banco (A).

 

Manifestação de rebanho: Considerando a manifestação de “rebanho” da sociedade alemã, um dos vieses mais proeminente no comportamento de grupos, Bonhoeffer sugeriu que a estupidez é orgulhosa de si mesma, principalmente quando o indivíduo recebe a chancela do grupo, da “maioria”. Para ele, conhecer a natureza da estupidez é urgente para evitar ela predomine e cause danos graves à sociedade.

Existe um evento descrito pelo neurologista inglês Oliver Sacks sobre como foi a recepção do discurso do presidente dos EUA, Ronald Regan, transmitida pela TV e observado em um ambiente de um hospital psiquiátrico. Os pacientes com transtornos gerais de esquizofrenia e portavam dois tipos de disfunção cognitiva: aqueles com afasia global são incapazes de compreender os sentidos das palavras em seu sentido literal, e se apegavam aos aspectos não verbais do discurso; e aqueles com agnosia tonal, incapazes de compreender a expressividade da comunicação, sendo obrigados a se apegar ao texto literal da linguagem, de modo puramente semântico. Reagan não conseguiu persuadir ninguém daquele público restrito. Os pacientes se sentiram ultrajados, alternando suas reações entre risos e escárnio. Enquanto isso as pessoas ditas normais julgaram que Reagan era um grande comunicador, persuasivo e lógico.

Horrorizado com os absurdos da guerra e a aceitação tácita da sociedade alemã, Bonhoeffer passou a fazer oposição ferrenha ao grande grupo de cristãos que aderiram à ascensão do nazismo. Ele encontrou uma única explicação para o crescimento da intolerância e aceitação do regime totalitário que trouxe uma guerra total na Europa e no resto do mundo. Esse motivo era a estupidez – tornava-se urgente compreender a natureza dessa característica humana. Para isso era necessário se livrar da crítica moral: estupidez não é apenas falta de caráter. Na verdade, para ser estudada com consideração objetiva e científica ela deve ser tratada como uma categoria psico-sociológica.

A estupidez tem raízes profundas no psiquismo, impulsionada pelo funcionamento básico da experiência humana e o fato de que humanos são animais sociais. A própria sociabilidade está na base da estupidez. Pessoas que vivem isoladas, por qualquer motivo, estão menos vulneráveis a esse problemas, o que reforça a natureza social da estupidez. Um indivíduo pode agir de modo estúpido sem afetar seu ambiente social. Mas, quando a estupidez se difunde e é adotada pelo grupo, o indivíduo fica gravemente afetado, gerando um efeito de realimentação. O comportamento de rebanho é uma das causas principais da estupidez.

Bonhoeffer afirmava que “o poder de um precisa da estupidez do outro”. Isso não significa que o intelecto e outras habilidades fiquem atrofiadas ou desapareçam. A observação do fenômeno parece mostrar que, sob a pressão crescente de grupo, os indivíduos são privados de sua independência pessoal e desistem, de modo mais ou menos consciente, de manter sua autonomia em relação ao ambiente opressor. “Pessoas estúpidas são frequentemente teimosas, o que não significa que sejam independentes” (Bonhoeffer). Essas pessoas têm a sua parte lógica do cérebro prejudicada, passando a agir como zumbis políticos e sociais. Eles se apegam a slogans, palavras de ordem e gritos de guerra de nível emocional.

Com essa constatação Bonhoeffer fornece elementos para se compreender a história exótica sobre Ronald Reagan, contada por Oliver Sacks. Aqueles pacientes psiquiátricos estavam concentrados em seu mundo interior, distantes do convívio social. Isso os tornou imunes à loucura coletiva do pensamento conforme à pressão de massa. Eles enxergaram Ronald Reagan como um ator canastrão que mal conseguia concluir suas falas, nem passava sinais de autenticidade ou credibilidade.

Viéses Cognitivos

O uso de processamento de informações por meio de atalhos mentais (a chamada heurística) são resultado de um processo evolutivo especial que nos permite atingir conclusões e julgamentos rápidos, muito úteis para a nossa sobrevivência. Mas a mesma faculdade pode se transformar em vieses de cognição de muitas formas, de desvios sistemáticos de lógica e decisões irracionais. São partes desses desvios os ruídos mentais, crenças infundadas, a escalada irracional de compromisso, que consiste em persistir em uma decisão prejudicial que já recebu muito investimento. Entre estes desvios, o comportamento de manada, de seguir a maioria, é o mais proeminente. Podemos facilmente imaginar situações em nosso passado evolutivo onde, dentro de um grupo frágil de pequenos mamíferos, se torna importante aceitar a decisão da maioria, tal como quando se foge de um predador. Se a informação é escassa vale a pena fazer o mesmo que todos os demais estão fazendo. No entanto, é muito claro que isso não é uma boa decisão em todas as situações, principalmente na modernidade.

O estudo da História revela inúmeras situações em que a maioria estava errada, e que seguir o bando pode trazer resultados catastróficos. Por isso Bonhoeffer enfatizava que lutar contra a estupidez é mais difícil do que combater o mal. É mais fácil discernir as atitudes maléficas, expô-las para a coletividade e encontrar parceria para combater o mal. A estupidez , por outro lado, é difusa. O indivíduo não parece estar prejudicando voluntariamente as pessoas a seu redor. Além disso elas sempre têm um grupo de apoio. Canalhice e má-intenção são falhas de caráter individual. A estupidez é um fenômeno coletivo.

Canalhas e covardes devem se esconder para tirar vantagens pessoais, muitas vezes gerando infortúnio individual ou coletivo com seu comportamento imoral. A estupidez gera uma situação de amoralidade. Estúpidos se orgulham da própria estupidez porque são chancelados pelo grupo. Eles sabem que não estão sozinhos, se apoiam no coletivo e podem pedir ajuda. Humanos temem a solidão, e permanecem em grupos não pelo poder hipnótico de seus líderes, como já foi sugerido, mas sim pelo vínculo formado com eles e outros de seus subordinados. As redes sociais tornaram esse problema muito mais grave, com o seu poder de formação de bolhas, de amplificação da mensagem por meio de seguidores fiéis e de robôs, criando grandes manadas tomadas por vieses cognitivos. Nas palavras de Umberto Eco, a Internet deu voz a uma “legião de imbecis”. A uniformização do pensamento e a rejeição da autoridade, principalmente de natureza científica e acadêmica, são terreno fértil para a propagação da teorias da conspiração, para ambientes de ódio à grupos minoritários e para a radicalização das bolhas que hoje são praticamente impossíveis de serem rompidas. Tudo isso sem esquecer dos oportunistas que, mesmo sem participar inteiramente da bolha, fazem uso dela para atingir seus fins econômicos e políticos.

Bibliografia

Voce pode gostar de ler também aqui no Phylos.net:

Gerenciador de pacotes Flatpak

O que é Flatpak

Flatpak é um utilitário (um aplicativo) usado para a distribuição, instalação e gerenciamento de pacotes de software no Linux. Ele usa um sistema de sandbox que permite aos usuários rodar aplicativos em um ambiente de isolamento partial do resto do sistema. Flatpak é também o nome de estrutura usada para criar pacotes de desktop em muitas distribuições Linux. Sua força está em sua abordagem para a entrega de software. Ele remove restrições tradicionais e fornece uma resposta simples para programas de computador, independentemente da linguagem de programação, do hardware ou das  das arquiteturas de softwares que eles usam. Essa flexibilidade garante que os construtores possam usar o flatpak sem questionar problemas de compatibilidade.

Muitos outros sistemas de gerenciamento de pacotes existem para os diversos sistemas operacionais. Para o Linux temos, por exemplo:

  • dpkg: usado pelo Debian, Ubuntu e seus derivados, distribuindo arquivos no formato .deb. Foi o primeiro a apresentar um mecanismo de resolução de dependências, usando o aplicativo APT do lado do usuário.
  • RPM: criado pela Red Hat, agora é usado por diversas distribuições como PCLinuxOS, Fedora, AlmaLinux, CentOS, openSUSE, OpenMandriva e Oracle Linux. RPM lida com pacotes .rpm, sendo a base de gerenciadores como apt4rpm, up2date (Red Hat), urpmi (Mageia), zypper (openSUSE), e dnf (Fedora, Red Hat e Yellow Dog Linux). Leia aqui as instruções de uso de DNF4 e DNF5.
  • Pacman: Usado no Arch Linux, Frugalware e DeLi Linux, é um formato de pacotes binários e comprimidos por tar. Os pacotes são gerenciados pelo utilitário makepkg.
  • Snap: um gerenciador desenvolvido pela CAnonical para o Ubuntu. Os pacotes, chamados snaps são gerenciados pela ferramenta snapd, usado por diversas distribuições. Como o flatpak também cria ambientes de isolamento dentro do sistema.
  • AppImage: não é propriamente um gerenciador de pacotes mas sim uma forma de distribuição de arquivos binários executáveis que podem ser redados em qualquer distibuição linux, sem a necessidade de ajusta para cada uma. As imagens em AppImages trazem contêm todas as dependências necessárias para a execução do aplicativo.

Conceitos básicos

Alguns conceitos são essenciais para a compreensão do flatpak. Ainda que existam aplicativos GUI para gerenciar os pacotes, é útil aprender os comandos na CLI (command line interface).

O que é Sandbox

sandbox é um mecanismo de segurança na computação, usado inicialmente no desenvolvimeto de softare para garantir que um código esteja logicamente isolado do sistema operacional do computador e outros aplicativos instalados. Ele contêm, em princípio, todas as dependências necessárias, embora existam sistemas em que parte dessas dependências pode ser encontrada no computador hospedeiro. Desta forma, é possível escolher exatamente as versões de cada dependência e outros recursos usados no desenvolvimento, evitando falhas e impedindo que vulnerabilidades se espalhem pelo sistema. O isolamento nas sandboxes significa que um processo externo a ela não pode interferir em um processo interno, e vice-versa.

Mais tarde, o mesmo conceito passou a ser usado para a própria instalação e execução de aplicativos nos computadores de usuários, criando ambientes isolados que restringem o seu acesso ao sistema operacional, limitando possíveis danos que um aplicativo malicioso ou com falhas de segurança pode causar. Essa é também uma forma de garantir que o aplicativo tenham acesso às dependências corretas e que a instalação de novos aplicativos não prejudiquem o sistema e os demais aplicativos instalados.

Cada aplicativo flatpak é criado e executado em seu próprio ambiente isolado (sandbox), que contém o aplicativo e todas as dependências necessárias para sua execução (runtime). Por default, o aplicativo só pode acessar a sua própria sandbox, embora seja possível dar permissões para seu acesso a arquivos de usuário, rede, soquetes gráficos e algns componentes do hardware. Alguns recursos, como outros processos em execução no host, são deliberadamente vedados. Em algumas situações alguns recursos dentro do sandbox precisam ser exportados para fora, para serem usados ​​pelo host. Esses recursos são denominados “exportações”, incluindo o arquivo de desktop do aplicativo com seu ícone.

Sandboxes, máquinas virtuais e conteineres: Uma máquina virtual é um ambiente virtualizado (isolado dentro do sistema operacional) que simula um sistema operacional completo. Por sua vez, um container isola um aplicativo e suas dependências em um ambiente virtualizado, compartilhando no entanto o kernel do sistema operacional hospedeiro. Os três conceitos são semelhantes, cada um com características próprias e propósitos específicos. Enquanto uma sandbox é mais genérica e pode ser usada para executar diversos tipos de programas de forma segura, uma máquina virtual simula um sistema operacional completo e é ideal para testes e desenvolvimento de software. Já um container é mais leve e ágil do que uma máquina virtual, sendo mais adequado para implementação e execução de aplicativos de forma isolada.

Repositório

Um repositório de software, ou repo, é um local de armazenamento para pacotes de software. Geralmente eles possuem uma lista de aplicativos disponibilizados, juntos com os seus metadados e runtime (as depedências). Repositório de software são gerenciado por controle de versão, e trabalham junto com gerenciadores de pacotes que permitem instalar e atualizar e gerenciar pacotes no computador do cliente.


Alguns dos repositórios de pacotes flatpak são:

  • Flathub: o maior e mais popular repositório.
  • GNOME Software: repositório oficial para o GNOME, com aplicativos projetados para o ambiente GNOME.
  • KDE Discover: repositório oficial para o KDE, com aplicativos otimizados para o ambiente KDE Plasma.
  • Elementary AppCenter: do Elementary OS.
  • Manjaro Community Repository: para a distribuição Manjaro Linux.

O principal repositório de pacotes flatpak atualmente (em dezembro de 2024) é o Flathub.

O Flathub fornece listas separadas para pacotas Trending, Popular, New, Updated e Verified. Aplicativos verificados no Flathub são aqueles mantidos diretamente pelo desenvolvedor ou algum grupo autorizado ou aprovado por ele. Aplicativos verificados aparecem com um ícone azul na página de seleção. Também existem aplicativos publicados no Flathub pela comunidade ou por terceiros, não mantidos pelo desenvolvedor original. Esses apps não são elegíveis para verificação.

Repositórios do flatpak se comportam de forma semelhante aos repositórios Git: um repositório flatpak pode conter um ou vários objetos, e cada um marcado com sua versão, permitindo atualizações ou downgrades. Cada sistema flatpak pode ser configurado para acessar um ou diversos repositórios remotos. Se um repositório é declarado em um sistema, torna-se possível acessar o conteúdo do repositório remoto, pesquisando a baixando dele aplicativos e runtimes. Em uma atualização, novas versões de aplicativos e runtimes são baixadas dos remotos relevantes. Como ocorre com o Git, apenas as partes alteradas entre as versões são baixadas, tornando o processo muito eficiente.

O manual do flatpak fornece instruções sobre como construir repositórios: Hosting a Repository.

Runtimes, bibliotecas empacotadas e portais

Runtimes: runtimes (ou ambiente de execução) são o conjunto das dependências básicas usadas pelos aplicativos. Todo aplicativo é criado no contexto de um runtime, que deve ser instalado no sistema host para que o aplicativo funcione adequadamente. O flatpak cuida da instalação do runtime necessário. Vários runtimes, com diferentes versões, podem ser instalados e usados lado a lado. Runtimes são independentes de distribuição e versão, fornecendo uma base estável para que os aplicativos funcionem independentemente das atualizações do sistema operacional.

Bibliotecas empacotadas, (bundled libraries): Se um aplicativo exige dependências não contidas em seu runtime, elas podem ser empacotadas junto com o aplicativo. Dessa forma os desenvolvedores têm flexibilidade na escolha de dependências, permitindo o uso de (a) bibliotecas não disponíveis em tempo de execução; (b) bibliotecas com versões diferentes das disponíveis no sistema; (c) versões corrigidas de bibliotecas.

Portais: portais são um mecanismo usados pelos aplicativos para interagir com o host, a partir de sua sandbox. Eles permitem o acesso a dados, arquivos e serviços sem necessitar de permissões adicionais. São exemplos de recursos acessados ​​por portais: abrir arquivos por meio de uma caixa de diálogo (seletor de arquivos) ou imprimir. Existem kits de ferramentas que oferecem suporte seguro e transparente para portais. Outras informações sobre portais podem ser encontradas em Permissões do Sandbox: Sandbox Permissions.

Flatpak, instalação e uso

Usamos aqui as seguintes convenções:
# linhas de comentários
$ linhas de código (input)
➡ linhas de saída (output)

Para instalar o flatpak em seu sistema, siga estas etapas:

# antes de instalar, atualize os pacotes do sistema atual
$ sudo apt update && upgrade      # no debian, ubuntu, etc 
$ sudo dnf update                 # no fedora

#  instale o Flatpak 
$ sudo apt install flatpak        # no debian, ubuntu, etc 
$ sudo dnf install flatpack       # no fedora
$ sudo zypper install flatpak     # no openSUSE
$ sudo pacman -S flatpak          # no arch linux
 
$ sudo apt install gnome-software-plugin-flatpak        # no debian, ubuntu, etc 
$ sudo dnf install gnome-software-plugin-flatpak        # no fedora

# para instalar os aplicativos precisamos adicionar o repositório remoto (flathub)
$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

# para verificar a instalação, podemos ver qual versão foi instalada
$ flatpak --version
➡ Flatpak 1.15.12

Para ver o procedimento de instalação para outras distros consulte Flathub Setup.

Se a instalação foi bem sucedida, podemos instalar pacotes flatpak. Instalações de aplicativos podem ser feitas apenas para o usuário (o app fica disponível apenas para aquele usuário) ou no sistema inteiro (o app fica disponível para todos os usuários do sistema). Abrimos o terminal e executamos:

# instalação global
$ flatpak install flathub com.jeffser.Alpaca
# após um pedido de confirmação a instalação é concluída

# para instalar apenas para o usuário (<remote> é o repositório, <name&gt nome do app)
$ flatpak install --user <remote> <name>
    
# se nenhuma mensagem de erro for emitida o aplicativo pode ser executado com
$ flatpak run <name>


Para encontrar o nome do aplicativo visitamos o repositório de pacotes no Flathub, onde uma lista de aplicativos será exibida. Digamos, por exemplo, que queremos instalar o Alpaca, um gerenciador de servidores de Inteligências Artificiais. Pesquisamos Alpaca e encontramos:

  • Comando para instalação: flatpak install flathub com.jeffser.Alpaca
  • Comando para executar o app: flatpak run com.jeffser.Alpaca

Portanto executamos o código:

# instalação global
$ flatpak install flathub com.jeffser.Alpaca

# para instalar apenas para o usuário logado
$ flatpak install --user flathub com.jeffser.Alpaca

Para evitar as perguntas de confirmação, respondendo yes (sim) para todas as perguntas, use o parâmetro -y:

$ flatpak install flathub com.jeffser.Alpaca -y

É possível, dependendo do sistema, que apenas o primeiro passo da instalação seja necessário e o aplicativo fique integrado ao sistema. Nesse caso basta abrir o menu utilizado e clicar em seu ícone.

Nota: se você tem diversos aplicativos para instalar, e o faz regularmente, para reinstalar e atualizar o sistema operacional, você pode armazenar um artigo de texto contendo os comandos de instalações, separados por &&. Para reinstalá-los basta copiar o texto e colá-lo no terminal. (A maioria dos terminais Linux recebem colagem da área de transfrência com CTRL-SHIFT-V.)

Por exemplo, para instalar o WPSOffice, Geany e Zed, cole no terminal:

flatpak install flathub com.wps.Office -y && 
flatpak install flathub org.geany.Geany -y &&
flatpak install flathub dev.zed.Zed -y

Desinstalação de pacotes:

Uma vez instalado um aplicativo, ele pode ser desinstalado (removido do sistema) com o seguinte comando:

$ sudo flatpak uninstall <nome do pacote/aplicativo>

# por exemplo, para desinstalar o alpaca
$ flatpak uninstall com.jeffser.Alpaca -y

# podemos usar o alias remove
$ flatpak remove <nome do pacote/aplicativo>

Nota: Na desinstalação deve-se usar o mesmo nome com que o aplicativo foi instalado.

Atualizando ou rebaixando a versão de pacotes

O flatpak fornece funcionalidade de atualização de aplicativos instalados através do seguinte comando:

# atualizar    
$ sudo flatpak update <nome do pacote/aplicativo>

# ex.: para atualizar o alpaca
$ sudo flatpak update com.jeffser.Alpaca

# para atualizar aplicativo instalado para o usuário apenas
$ flatpak update --user com.jeffser.Alpaca

Também é possível rebaixar a versão instalada de algum aplicativo. Suponha, por exemplo, que necessitamos de uma versão anterior do navegador Brave. Primeiro pesquisamos no repositório informações sobre o navegador, com remote-info --log flathub, onde podemos encontrar versões anteriores disponíveis.

# para ver informações sobre o Brave    
$ flatpak remote-info --log flathub com.brave.Browser
➡ Brave - Fast Internet, AI, Adblock
        ID: com.brave.Browser
       Ref: app/com.brave.Browser/x86_64/stable
      Arch: x86_64
    Branch: stable
   Version: 1.73.101
   [truncado]
 
    Commit: 852620f9b5998b4cbfd621cf523e4367ba80b517427c810b8166eb48aa9f50db
   Subject: version update (7d8acf2a)
      Date: 2024-11-20 17:56:11 +0000
  [truncado]

# escolhemos a versão update (7d8acf2a) e anotamos o código de commit
# fazemos o update para aquele commit  
$ sudo flatpak update \
      --852620f9b5998b4cbfd621cf523e4367ba80b517427c810b8166eb48aa9f50db \
      com.brave.Browser

Gerenciando repositórios

Para adicionar um repositório no flatpak usamos:

# adicionar repositório
$ sudo flatpak remote-add --if-not-exists [name] [location]

# ex: adicionar o repositório do FlatHub repository
$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

# depois de instalado podemos procurar um pacote no repo
# procurando o gimp
$ flatpak search gimp
➡ Name                   Description            Application ID                Version     Branch           Remotes
  GIMP User Manual       GIMP User Manual       org.gimp.GIMP.Manual           2.10        2.10            flathub
  GNU Image Manip…       Create images and...   org.gimp.GIMP                  3.0.0~rc1   stable          fedora,flathub
  GimpLensfun            Lensfun Gimp plugin    org.gimp.GIMP.Plugin.Lensfun   0.2.4       2-40            flathub
  Fourier                Fourier GIMP Plugin    org.gimp.GIMP.Plugin.Fourier   0.4.5       2-40            flathub
  [lista truncada]

# para instalar o GIMP do repo Flathub
$ sudo flatpak install flathub org.gimp.GIMP

Se existirem mais de um repositório adicionados as várias opções disponíveis serão exibidas, como mostrado no exemplo acima. Você pode escolher qual pacote instalar, e de qual repositório. No caso foi instalado o org.gimp.GIMP, obtido no repositório flathub. Se não houver ambiguidade o nome do reposiório pode ser omitido.

Podemos listar quais são os repositórios cadastrados localmente com o flatpak. Para isso usamos remote-list. Para remover um desses repositórios da lista usamos remote-delete:

# listar repos cadastrados (existem apenas 2)
$ flatpak remote-list
➡ Name    Options
  fedora  system,oci
  flathub system

# podemos remover um repo
$ flatpak remote-delete flatub

Se existirem aplicativos ou runtimes instalados à partir desse repositório, surgirá a opção de remover ou não esses apps. Para remover apenas o repositório, deixando os aplicativos inalterados, usamos:

$ flatpak remote-delete --force <nome-repositorio>

Permissões e Sandboxing

Por default os aplicativos Flathub podem ser instalados com permissões mais amplas que as exigida no sistema ou desejadas pelo usuário, para que um número maior de usuários sejam atendidos por essa instalação. Como exemplo, o Brave tem instalação default com –socket=pcsc (entre outras) para acesso por cartão inteligente. Se o usuário não tem um desses cartões ele pode desejar modificar as permissões para melhorar a segurança.

# para mostrar as permissões
$ flatpak info --show-permissions com.brave.Browser
➡ [Context]
   shared=network;ipc;
   sockets=x11;wayland;pulseaudio;pcsc;cups;
   devices=all;
   [truncado]

# alterar a permissão
$ flatpak override --user --nosocket=pcsc com.brave.Browser

# verifica o estado
$ flatpak override --user --show com.brave.Browser
➡ [Context]
  sockets=!pcsc;

# para ressetar todas as alterações
$ flatpak override --user --reset com.brave.Browser

Existem várias ferramentas GUI disponíveis, como Flatseal, GNOME Settings e KDE Settings, que permitem alterar essas permissões em um ambiente de janelas.

Aplicativos instalados e histórico de operações

Para listar os aplicativos e runtimes instalados com flatpack usamos flatpak list. Para listar apenas os aplicativos instalados, flatpak list --app e apenas os ambientes, flatpak list --runtime.

# lista de aplicativos e runtimes
$ flatpak list
➡ Name             Application ID                        Version
  Bitwarden        com.bitwarden.desktop                 2024.12.0
  Mesa             org.freedesktop.Platform.GL.default   21.3.9
  Brave            com.brave.Browser                     1.73.101
  Alpaca           com.jeffser.Alpaca                    2.9.0
  ZapZap           com.rtosta.zapzap                     5.3.9
  Sigil            com.sigil_ebook.Sigil                 2.2.0
  Zed              dev.zed.Zed                           v0.165.4
  Obsidian         md.obsidian.Obsidian                  1.7.7
  SiYuan           org.b3log.siyuan                      3.1.15
[a lista está truncada]

# lista apenas de aplicativos
$ flatpak list --app
➡ Name            Application ID               Version
  Bitwarden       com.bitwarden.desktop        2024.12.0
  Brave           com.brave.Browser            1.73.101
[a lista está truncada]

# lista apenas de runtimes
$ flatpak list --runtime
➡ Name                       Application ID                       Version
  Codecs                     org.audacityteam.Audacity.Codecs      stable
  Mesa                       org.freedesktop.Platform.GL.default   21.3.9
  GNOME App Platform v. 47   org.gnome.Platform                    47                  
[a lista está truncada]

Além das colunas mostradas ainda temos informações sobre Branch, Origin, Installation, não exibidas.

Para obter um histórico de operações realizadas com flatpak usamos:

$ flatpak history
➡ Time               Change           Application                           Branch      Installation     Remote
   Dec 13 11:08:56   add remote                                                          system          fedora
   Dec 13 11:08:56   add remote                                                          system          fedora-testing
   Dec 13 11:10:42   add remote                                                          system          flathub
   Dec 13 11:57:21   deploy install   org.freedesktop.Platform.GL.default    23.08       system          flathub
   Dec 13 11:57:24   deploy install   org.freedesktop.Platform.GL.default    23.08-extra system          flathub
   Dec 13 11:57:24   deploy install   org.freedesktop.Platform.Locale        23.08       system          flathub
[a lista está truncada]

Para renovar e reparar o sistema de referências a repositórios do flatpak, usamos
. A remoção de extensões e runtimes não usados por qualquer um dos aplicativos instalados, usamos uninstall --unused.

$ sudo flatpak repair 
➡ Working on the system installation at /var/lib/flatpak
  [175/175] Verifying flathub:runtime/com.bitwarden.desktop.Locale/x86_64/stable… # os aplicativos e runtimes são verificados
  Checking remotes...
  
# para eliminar 
$ flatpak uninstall --unused
➡ Nothing unused to uninstall  


A reparação de uma instalação do flatpak faz uma verificação geral das referências disponíveis localmente, removendo aquelas que não correspondem a pacotes instalados. Ela também remove as referências a objetos inválidos e aqueles que não estão referenciados por nenhum aplicativo. Finalmente ela enumera as referências instaladas e reinstala aquelas que não estão completas.

Informações sobre pacotes instalados podem ser vistas com:

$ flatpak info com.jeffser.Alpaca
➡ Alpaca - Chat with local AI models
          ID: com.jeffser.Alpaca
         Ref: app/com.jeffser.Alpaca/x86_64/stable
        Arch: x86_64
      Branch: stable
     Version: 2.9.0
     License: GPL-3.0-or-later
  [saída truncada]

Executando e pesquisando

flatpak run <aplicativo> executa (roda) o <aplicativo>.
Por exemplo, vimos no output de flatpak list que o nome identificador (id) do navegador Brave é com.brave.Browser. Portanto podemos rodar o aplicativo usando o comando:

# para executar o aplicativo do Brave    
$ flatpak run com.brave.Browser
➡ Gtk-Message: 19:18:19.612: Failed to load module "canberra-gtk-module"
# possíveis mensagens de erro, como a mostrada acima, são listadas no console

# uma lista de aplicativos em execução é exibida com ps
$ flatpak ps
➡ Instance   PID   Application       Runtime
  3817365666 3283  org.geany.Geany   org.freedesktop.Sdk
  846534418  16554 com.brave.Browser org.freedesktop.Platform
  1876930084 16599 com.brave.Browser org.freedesktop.Platform

# para fechar um aplicativo usamos kill 
$ flatpak kill com.brave.Browser
# o Brave (duas instâncias) é fechado

Utilitários GUI

Algumas das funções de gerenciamento de pacotes podem ser executadas através de aplicativos com interface gráfica. Atualmente no repositório Flathub encontramos, por exemplo:

Easy Flatpak: uma loja de aplicativos flatpak, que auxilia na instalação de aplicativos de uma forma amigável, apenas clicando nos botões. Em alguns casos existem receitas para aperfeiçoar algumas instalações, como no caso do Steam, que permite ao usuário escolher o diretório de armazenamento dos jogos.

Flatseal: um utilitário gráfico que permite a visualização e edição das permissões de aplicativos flatpak.

Flatsweep: permite a remoção de arquivos e dependência eventualmente deixados na remoção de um pacote.

Warehouse: fornece uma IU simples para controlar opções complexas do flatpak, sem recorrer à linha de comando. Com ele é possível:

  • gerenciar Flatpaks instalados e visualizare propriedades dos pacotes,
  • alterar versões de um Flatpak e reverter atualizações indesejadas,
  • fixar os runtimes e mascarar Flatpaks (para evitar atualizações),
  • filtrar pacotes e classificar dados para tornar as buscas mais eficientes,
  • consultar dados atuais do usuário do aplicativo, limpando dados desnecessários,
  • adicionas repositórios do Flatpak,
  • fazer instantâneos (snapshots) de dados do usuário e aplicativos para backup,
  • instalar pacotes de qualquer repositório remoto ou pacotes baixados.

Resumo dos comandos

Uso: flatpak [OPTION…] COMMAND

Opção de ajuda: flatpak -h ou flatpak --help exibe a lista de comandos do flatpak.

Comandos internos (Built in): gerencia aplicativos e runtimes instalados

install Instala aplicativo ou runtimes
update Atualiza um aplicativo ou runtime instalados
uninstall Desinstala um aplicativo ou runtimes
mask Aplica máscara para excluir atualizações e instalações automáticas
pin Trava um runtime para impedir a remoção automática
list Lista aplicativos e/ou runtimes instalados
info Mostra informações sobre aplicativos ou runtimes instalados
history Lista o histórico
config Configura o flatpak
repair Repara a instalação do flatpak
create-usb Coloca aplicativos ou runtimes em mídia removível

Busca de aplicativos e runtimes

run Executa um aplicativo
override Sobreescreve as permissões de um aplicativo
make-current Especifica qual a versão padrão a ser executada
enter Insire o namespace de um aplicativo em execução
ps Lista os aplicativos em execução
kill Interrompe a execução de um aplicativo

Gerencia o acesso a arquivos:

documents Lista arquivos exportados
document-export Concede a um aplicativo acesso a um arquivo específico
document-unexport Revoga acesso a um arquivo específico
document-info Mostra informações sobre um arquivo específico

Gerencia permissões dinâmicas

permissions Lista permissões
permission-remove Remove item do armazenamento de permissões
permission-set Define permissões
permission-show Mostra permissões do aplicativo
permission-reset Redefine permissões do aplicativo

Gerencia repositórios remotos

remotes Lista todos os repositórios remotos configurados
remote-add Adiciona um novo repositório remoto (por URL)
remote-modify Modifica propriedades de um repo remoto configurado
remote-delete Excluir um repo remoto configurado
remote-ls Lista o conteúdo de um repositórioa configurado
remote-info Exibe informações sobre aplicativo remoto ou runtime

Construção de aplicativos

build-init Inicializa um diretório para construção
build Executa um comando dentro do diretório de construção
build-finish Conclui um diretório de construção para exportação
build-export Exporta diretório de construção para um repositório
build-bundle Cria um arquivo de pacote usando referência a repositório local
build-import-bundle Importa um arquivo de pacote
build-sign Assina um aplicativo ou runtime
build-update-repo Atualiza o arquivo de resumo de um repositório
build-commit-from Cria novo commit com base na referência existente
repo Exibe informações sobre um repositório

Opções do aplicativo:

–version Imprime informações sobre a versão e termina
–default-arch Imprime a arquitetura padrão e termina
–supported-arches Imprime as arquiteturas suportadas e termina
–gl-drivers Imprime os drivers gl ativos e termina
–installations Imprime caminhos para instalações do sistema e termina
–print-updated-env Imprime o runtime atualizado necessário para execução de flatpaks
–print-system-only Inclui apenas a instalação do sistema com –print-updated-env
-v, –verbose Mostra informações de depuração, -vv para mais detalhes
–ostree-verbose Mostra informações de depuração do OSTree

Nota †: No contexto do flatpak, runtime, também chamado de platforma, é o ambiente integrado básico de utilitários que permite a execução de um aplicativo flatpak.

Bibliografia

DNF5: Gerenciador de Pacotes

DNF4 para DNF5

Já vimos nessas notas o funcionamento do DNF, gerenciador de pacotes de software no linux. Nessa ocasião o comando dnf se referia (era um aliás) para dnf4. O Fedora mudou do DNF4 para o DNF5 devido à necessidade de atualizar e melhorar o gerenciador de pacotes do sistema operacional. O DNF5 foi construído pelo esforço coletivo das equipes do Fedora e do Red Hat, e traz várias vantagens em relação à versão anterior, incluindo melhor desempenho, maior estabilidade, correções de bugs e melhorias na interface do usuário. Além disso, o DNF5 oferece suporte a novas funcionalidades e melhor integração com outros componentes do sistema operacional. O DNF5 está instalado no Fedora desde a versão 38, não sendo o gerenciador de pacotes padrão, por default. No Fedora 41 ele é instalado como padrão, e recebe o álias dnf. A versão anterior está ainda disponível, bastando digitar dnf4 na linha de comando. Uma página da documentação descreve as alterações entre dnf4 para dnf5, em Changes between DNF4 and DNF5.

O que é um gerenciador de pacotes?

Um gerenciador de pacotes é um conjunto de aplicativos usados para automatizar o processo de instalação, atualização, configuração e remoção de programas de computador de uma maneira consistente. Ele manipula pacotes, que são distribuições de software e dados, contendo metadados como o nome do software, descrição de propósito, versão, fornecedor, checksum e uma lista de dependências necessárias. Na instalação, os metadados são armazenados em um banco de dados local. Gerenciadores de pacotes usam esse banco de dados de dependências para evitar incompatibilidades de software e pré-requisitos ausentes. Eles trabalham em conjunto com os repositórios de software, algumas vezes acessados pelas lojas de aplicativos. Diversas distribuições Linus usam DNF (ou YUM), entre elas: RedHat Enterprise Linux, Fedora, CentOS, Oracle Enterprise Linux, SUSE, OpenSUSE, Mageia e Turbolinux.

Nessas notas descreveremos o aplicativo DNF5 sem fazer alusão alusão ao artigo anterior, para que ele possa ser lido independentemente.

Usamos aqui as seguintes convenções:
# linhas de comentários
$ linhas de código (input)
➡ linhas de saída (output)

O que é RPM?

O RPM Package Manager (RPM) é um sistema de gerenciamento de pacotes de código aberto. Os arquivos que ele empacota recebem a extensão .rpm. O gerente RPM foi criado para uso no Red Hat Linux, mas agora é usado em muitas distribuições Linux, como PCLinuxOS, Fedora Linux, AlmaLinux, CentOS, openSUSE, OpenMandriva e Oracle Linux.

Um pacote RPM pode conter um número variado de arquivos. A maioria deles são “RPMs binários” (ou BRPMs), que contém a versão já compilada de algum software. Também existem “RPMs de origem” (ou SRPMs) que trazem o código-fonte usado para construir um pacote binário. Nesse caso eles têm uma tag no cabeçalho do arquivo que os marca como SRPM e faz com que esses arquivos sejam extraídos para /usr/src na instalação.

Repositórios: RPMs são frequentemente coletados em um ou mais repositórios na internet, chamados repositórios. Alguns sites replicam esses repositórios, nos espelhos locais (ou mirrors). Aplicativos destinados a faciltar o uso desses arquivos, gerenciando instalações, dependências e conflitos são os front ends. Alguns exemplos são: YUM (a base para o dnf); DNF; up2date; Zypper, urpmi, apt-rpm, uma adaptação para usar pacotes rpm no Debian, entre outros.

Banco de dados de instalação local: o gerenciador de pacotes usa uma banco de dados (rpmdb), armazenado em /var/lib/rpm. Diversos gerenciadores podem ser usados, como o SQLite ou Berkeley DB, contendo todas as meta informações dos pacotes instalados. É possível identificar qual o gerenciador está sendo usado com o comando rpm --showrc. Esse banco de dados indexa a informção para acelerar as consultas, e mantém o controle de todos os arquivos alterados e criados pelo usuário, permitindo a reversão das alterações e remoção de pacotes. Em caso de corrupção desse banco de dados de índice, eles podem ser recriados com o comando rpm --rebuilddb.

# para descobrir o dbms usado pelo rpm
$ rpm --showrc

# para restaurar banco de dados corrompido
$ rpm --rebuilddb

O que é DNF5?

O DNF5 é um gerenciador de pacotes que automatiza o processo de instalação, atualização, configuração e remoção de programas de computador de forma consistente. Ele suporta pacotes RPM, módulos modulemd e grupos e ambientes comps. libdnf é a biblioteca de gerenciamento de pacotes, escrita originalmente para suportar o gerenciador de pacotes DNF, mas gradualmente cresceu e se tornou uma biblioteca versátil. Agora é possível usar libdnf para construir ferramentas personalizadas que carregam repositórios, resolvem dependências, consultam e instalam pacotes. O DNF5 também é alimentado pela biblioteca libsolv, que fornece uma interface de programação fácil de usar.

O DNF5 você pode trabalhar com os seguintes artefatos:

  • Repositórios e pacotes RPM: descritos acima.
  • Módulos modulemd: modulemd é um arquivo que define quais pacotes são construídos para cada versão do sistema operacional. Ele inclui um resumo e uma descrição, uma lista de pacotes RPM de origem, informações sobre a ordem em que os aplicativos são instalados, junto com macros e informações de uso, ou seja, perfis de instalação e licenças.
  • Ambientes e grupos comps, Metadados de composição da distribuição (Distribution Compose Metadata): Objetos comps reune informações sobre todos os repositórios disponíveis.
  • Avisos (updateinfo, erros): Avisos são mensagens informativas que não impedem a conclusão do comando DNF mas indicam problemas potenciais e sugerem alternativas. Updateinfo é um metadado com informações sobre atualizações disponíveis para pacotes. Quando o DNF encontra updateinfo, ele pode exibir informações sobre atualizações disponíveis, incluindo o nome do pacote, versão e repositório. Updateinfo não é um erro, mas sim uma notificação sobre atualizações disponíveis. Erros são mensagens críticas que impedem a conclusão do comando DNF. Eles podem informar da ausência de dependências, erros no repositório, etc.

Instalação

Para instalar o gerenciador de pacotes DNF5, use um dos seguintes comandos, dependendo da sua versão do Fedora. Verifique antes se ele já não está instalado.

# no Fedora 37 ou outro sistema sem a instalação do repositório
$ sudo dnf copr enable rpmsoftwaremanagement/dnf-nightly 
# instalando 
$ sudo dnf install dnf5

# no Fedora 38+ o repositório já está incluído
$ sudo dnf install dnf5
	
# verifique qual versão instalada, e em que diretório.
$ which dnf5
➡ /usr/bin/dnf5
 
# ou 
$ dnf5 --version
➡ dnf5 version 5.2.7.0
  dnf5 plugin API version 2.0
  libdnf5 version 5.2.7.0
  libdnf5 plugin API version 2.0
 [truncado]

Os seguintes comandos são de uso frequente com o dnf (usado como álias para o dnf5):

Comandos:

Comando, aliás Descrição
$ dnf upgrade <pacote> Atualiza o sistema e pacotes para a versão mais recente.
$ dnf search <pacote> Pesquisa pacotes disponíveis no repositório do sistema.
$ dnf install <pacote> Instala um nova pacote especificado pelo nome.
$ dnf remove <pacote> Remove pacotes instalados especificaods pelo nome.
$ dnf distro-sync <pacote> Sincronize os pacotes instalados com as versões mais recente disponíveis nos repositórios para a versão atual do Fedora.
$ dnf repoquery <pacote> Pesquisa a informação sobre o pacote especificado nos repositórios DNF.
$ dnf list <pacote> Exibe informações sobre pacotes que se ajustem à especificação.
$ dnf info <pacote> Coleta informação detalhada sobre o pacote especificado.
$ dnf makecache Refaz e atualiza o cache de metadata do gerente de pacotes DNF.
$ dnf repolist Exibe a lista de repositórios junto com informações sobre o número de pacotes disponíveis em cada repositório.
$ dnf repoinfo Exibe informação sobre os repositórios configurados no sistema.

As páginas do manual do aplicativo podem ser visualizados com man dnf, para ajuda geral, ou man dnf list para a ajuda sobre o parâmetro específico list ou outro qualquer.

Exemplos de uso do dnf

Alguns exemplos podem ajudar a compreender o uso do dnf. Observe que algumas operações exigem o uso do sudo.
O comando sudo (Super User DO) é usado como um prefixo para comandos que só podem ser executados por superusuários, aqueles que têm permissão. Isso faz com que o comando após o sudo seja executado com privilégios elevados. Vários usuários podem ter acesso ao sudo, desde que estejam declarados como administradores no arquivo sudoers em /etc/sudoers. Por padrão, esses usuários executam funções administrativas usando as suas próprias senhas.

upgrade, search, install, remove

No exemplo abaixo lidamos com a pesquisa, instalação e remoção do aplicativo featherpad, um editor de texto puro usando Qt.

Exemplos de uso:

# fazer a atualização do pacote featherpad
$ sudo dnf upgrade featherpad
➡ Updating and loading repositories:
  Repositories loaded.

# pesquisar pelo pacote nos repositórios cadastrados 
$ dnf search featherpad
➡ Updating and loading repositories:
  Repositories loaded.
  Matched fields: name (exact)
  featherpad.x86_64: Lightweight Qt Plain-Text Editor

# instalar a pacote, que deve estar nos repositórios cadastrados 
$ sudo dnf install featherpad
➡ Updating and loading repositories:
  Repositories loaded.
  Package                   Arch           Version         Repository         Size
  Installing:
featherpad              x86_64         1.5.1-1.fc41    fedora             3.4 MiB

  Transaction Summary:
   Installing:         1 package

  Total size of inbound packages is 893 KiB. Need to download 893 KiB.
  After this operation, 3 MiB extra will be used (install 3 MiB, remove 0 B).
  Is this ok [y/N]: y
# featherpad-0:1.5.1-1.fc41.x86_64 é instalado e pode ser usado
$ featherpad
                                                                                                                                  
# desinstalar o aplicativo featherpad
$ sudo dnf remove featherpad
➡ Package            Arch          Version         Repository            Size
  Removing:
   featherpad      x86_64           1.5.1-1.fc41   fedora                  3.4 MiB
  Transaction Summary:
Removing:  1 package
  Is this ok [y/N]: y
# o featherpad é removido do sistema

# para evitar que a execução seja interrompida por perguntas use
$ sudo dnf install featherpad -y
$ sudo dnf remove featherpad -y

Os comandos de instalação e remoção perguntam ao usuário: Is this ok [y/N]: , sendo que a resposta “Não” é o default. Para responder Yes para todas as perguntas use a chave -y (ou -n para responder No).

makecache, repolist, repoinfo

Também podemos gerenciar, inserindo ou removendo os repositórios cadastrados de acordo com as necessidades.

# para listar os repositórios cadastrados
$ dnf makecache
➡ Updating and loading repositories:
  Repositories loaded.
  Metadata cache created.
  
# para listar os repositórios cadastrados
$ dnf repolist
➡ repo id                                                            repo name
  copr:copr.fedorainfracloud.org:ryanabx:cosmic-epoch                 Copr repo for cosmic-epoch owned by ryanabx
  copr:copr.fedorainfracloud.org:wiiznokes:cosmic-applets-unofficial  Copr repo for cosmic-applets-unofficial owned by wiiznokes
  fedora                                                              Fedora 41 - x86_64
  fedora-cisco-openh264                                               Fedora 41 openh264 (From Cisco) - x86_64
  rpmfusion-free                                                      RPM Fusion for Fedora 41 - Free
  rpmfusion-free-updates                                              RPM Fusion for Fedora 41 - Free - Updates
  rpmfusion-nonfree                                                   RPM Fusion for Fedora 41 - Nonfree
  rpmfusion-nonfree-updates                                           RPM Fusion for Fedora 41 - Nonfree - Updates
  updates                                                             Fedora 41 - x86_64 - Updates

# para listar as propriedades dos repositórios
$ dnf repoinfo
➡ Updating and loading repositories:
  Repositories loaded.
  Repo ID             : copr:copr.fedorainfracloud.org:ryanabx:cosmic-epoch
  Name                : Copr repo for cosmic-epoch owned by ryanabx
  Status              : enabled
  Priority            : 99
  Cost                : 1000
  Type                : available
  Metadata expire     : 172800 seconds (last: 2024-11-15 14:08:04)
  Skip if unavailable : true
  Config file         : /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:ryanabx:cosmic-epoch.repo
  URLs                :
Base URL          : https://download.copr.fedorainfracloud.org/results/ryanabx/cosmic-epoch/fedora-41-x86_64/
  PGP                 :
Keys              : https://download.copr.fedorainfracloud.org/results/ryanabx/cosmic-epoch/pubkey.gpg
Verify repodata   : false
Verify packages   : true
  Repodata info       :
   Available packages : 626
Total packages    : 626
Size              : 22.9 GiB
Revision          : 1731404232
Updated           : 2024-11-12 09:37:12
# [truncado] segue as descrições dos demais repositórios registardos no computador

O comando dnf makecache é usado para baixar metadados para os repositórios habilitados, atualizando os dados locais. Ele tenta evitar o download de novos dados sempre que possível, por exemplo, quando os dados locais ainda não expiraram ou quando o carimbo de data/hora não foram alterados.

repolist é um aliás para repo list (ou seja, list é um parâmetro do comando repo), usado para listar os repositórios cadastrados. Se nenhum repositório estiver configurado ele não apresenta nenhum retorno. Da mesma forma repoinfo é um aliás para repo info, listando repositórios e suas propriedades.

Glossário

Especificação de padrões

Globs: globs são padrões que especificam um comjunto de nomes de arquivos usando caracteres “curingas” ou wildcard. Os padrões aceitos pelo dnf são os mesmos usados pela shell. Os seguintes padrões podem ser usados.

Definições:

* casa com qualquer número de caracteres, ou vazio.
? casa com um caracter único.
[xyz] casa com x, y ou z; qualquer um dos caracteres entre colchetes.
[a-z] casa qualquer um dos caracteres entre a até z, inclusive.
[!a-z] ou [^a-z] não casa com nenhum dos caracteres na faixa de a até z.
{ } colchetes não são suportados.

Exemplos:

*.txt casa com qualquer nome de arquivo que termina com .txt, como “texto.txt”, “aa.txt” ou “.txt”.
su*.css casa com “su.css”, “superman.css” ou “sucata.css”.
?asa.toml casa com qualquer nome de arquivo como “casa.toml”, “rasa.toml” ou “sasa.toml”.
??uga.pdf casa com “aluga.pdf”, “_ruga.pdf” mas não casa com “beluga.pdf”.
[a-m]luga.hlmt casa com “aluga.hlmt”, “gluga.hlmt”, “kluga.hlmt”, mas não com “pluga.hlmt”.
[!1-5]fix.jpg não casa com “3fix.jpg” nem “5fix.jpg”, mas casa com “7fix.jpg”.
[^1-5]fix.jpg o mesmo que acima.

Padrão NEVRA

Pacotes podem ser identificados exclusivamente pela string NEVRA, que consiste de 5 partes de informação:
Name | Epoch | Version | Release | Architecture

São eles: name do pacote (pode conter hifens), Epoch, um número, timestamp, nem sempre incluído, Version uma string, alfanumérica,Release da versão, Architecture, string definindo arquitetura do alvo.

Packages (Pacotes)

Muitos comandos usam o parâmetro <package-spec> para selecionar pacotes. Esse argumento é comparado com NEVRAs de pacotes, provides e file provides. Quando <package-spec> é um nome de pacote ou um provide, o usuário pode fornecer regras adicionais de restrição para corresponder aos argumentos. Comparações de versão podem usar os operadores lógicos =, >, <, >=, <= como, por exemplo, <package-spec>>= <version>, onde o argumento <version> está no formato [EPOCH:]VERSION[-RELEASE] conforme especificado acima.

<package-file-spec> é similar a <package-spec>, exceto que provides matching não é executado. Portanto, <package-file-spec> é correspondido somente com NEVRAs e file provides. <package-name-spec> é correspondido somente com NEVRAs.

Bibliografia