Projeto Lista de Tarefas
A Ana vive esquecendo coisas: comprar pão, pagar a conta de luz, levar o Rex ao veterinário. Neste projeto, ela ganha um programa de tarefas no terminal, com um menu: adicionar, ver, concluir, remover e sair. É o primeiro projeto do guia que guarda dados: primeiro numa lista, enquanto o programa está aberto, e no fim num arquivo, para as tarefas continuarem lá amanhã.
- Um menu que se repete, com while True e match e case.
- Listas: append(), pop(), índices e o índice
-1. - Numerar os itens com enumerate().
- Guardar cada tarefa num dicionário (
{"titulo": …, "feita": …}) e mudar um valor dele (alterando chaves). - Validar o número escolhido com
isdigit()e uma função que devolve a posição ou None. - Escrever e ler um arquivo de texto, e tratar o
FileNotFoundErrorcom try e except.
O que vamos construir
A lista pronta, no terminal da Ana. Ela abre o programa, cadastra três tarefas, conclui uma e sai. O que vem depois de Escolha:, Nova tarefa: e Número da tarefa: foi digitado por ela. Depois, o cat mostra o arquivo que o programa gravou:
$ python3 tarefas.py === Lista de Tarefas da Ana === 0 tarefa(s) carregada(s) de tarefas.txt. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Comprar pão Tarefa adicionada: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Pagar a conta de luz Tarefa adicionada: Pagar a conta de luz 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Levar o Rex ao veterinário Tarefa adicionada: Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: 2 Concluída: Pagar a conta de luz 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 0 Até mais! $ cat tarefas.txt [ ] Comprar pão [x] Pagar a conta de luz [ ] Levar o Rex ao veterinário
No dia seguinte, a Ana abre o programa de novo, e as tarefas estão lá:
$ python3 tarefas.py === Lista de Tarefas da Ana === 3 tarefa(s) carregada(s) de tarefas.txt. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 2 1. [ ] Comprar pão 2. [x] Pagar a conta de luz 3. [ ] Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 4 Número da tarefa: 1 Removida: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 0 Até mais! $ cat tarefas.txt [x] Pagar a conta de luz [ ] Levar o Rex ao veterinário
Quatro versões:
- O menu e a lista (
while True,match,append,enumerate). - Concluir e remover (dicionários,
pop). - Funções e número validado (
def,isdigit,None). - Guardar num arquivo (
opencom"w",FileNotFoundError).
Antes de começar
Este projeto usa o while True com match da Calculadora. Crie a pasta; o arquivo vai se chamar tarefas.py:
$ mkdir -p projetos/tarefas $ cd projetos/tarefas
Versão 1 · O menu e a lista
Todo programa de menu tem o mesmo esqueleto: um laço que mostra as opções, lê a escolha e faz o que foi pedido, até a pessoa escolher sair. As tarefas ficam numa lista de textos.
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append(titulo)
print(f"Tarefa adicionada: {titulo}")
case "2":
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, titulo in enumerate(tarefas, start=1):
print(f"{numero}. {titulo}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
- tarefas = []
- A lista começa vazia, fora do laço. Se ficasse dentro, seria esvaziada a cada volta do menu.
- print()
- Um
printsem nada escreve uma linha em branco: separa cada menu do anterior. - opcao = input("Escolha: ").strip()
- A opção fica como texto (
"1","2"…), semint(). Assim, se a pessoa digitarx, não há erro: cai nocase _. - tarefas.append(titulo)
- Acrescenta a tarefa no fim da lista (veja Adicionando Itens).
- if not tarefas:
- Uma lista vazia conta como falso: "se não há tarefas".
- for numero, titulo in enumerate(tarefas, start=1):
enumerate("enumerar") entrega, a cada volta, um par: o número e o item. Ostart=1faz a contagem começar em 1, como as pessoas contam (veja abaixo).- case "0": … break
- A única saída do laço.
$ python3 Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> tarefas = ["Comprar pão", "Pagar a luz"] >>> list(enumerate(tarefas, start=1)) [(1, 'Comprar pão'), (2, 'Pagar a luz')] >>> list(enumerate(tarefas)) [(0, 'Comprar pão'), (1, 'Pagar a luz')] >>> exit()
Sem o start=1, a contagem começaria em 0, que é como o Python numera as posições de uma lista (o primeiro item está na posição 0). Para mostrar à Ana, 1 é melhor. Guarde essa diferença: ela vai importar na versão 2.
$ python3 tarefas.py === Lista de Tarefas da Ana === 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 2 Nenhuma tarefa ainda. 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 1 Nova tarefa: Comprar pão Tarefa adicionada: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 1 Nova tarefa: Pagar a conta de luz Tarefa adicionada: Pagar a conta de luz 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 1 Nova tarefa: Levar o Rex ao veterinário Tarefa adicionada: Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 2 1. Comprar pão 2. Pagar a conta de luz 3. Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 5 Opção inválida. 1 - Adicionar tarefa 2 - Ver tarefas 0 - Sair Escolha: 0 Até mais!
Missão (versão 1): a opção 2 mostra a lista "crua", com colchetes e aspas: ['Comprar pão', 'Pagar a conta de luz']. Troque o print(tarefas) por um for com enumerate(tarefas, start=1) que mostre 1. Comprar pão, 2. Pagar a conta de luz. A entrada da missão cadastra as duas tarefas, escolhe 2 e sai.
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append(titulo)
print(f"Tarefa adicionada: {titulo}")
case "2":
print(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append(titulo)
print(f"Tarefa adicionada: {titulo}")
case "2":
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, titulo in enumerate(tarefas, start=1):
print(f"{numero}. {titulo}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
Versão 2 · Concluir e remover
Uma tarefa agora tem duas informações: o título e se já foi feita. Um texto só não basta; cada tarefa vira um dicionário com duas chaves, e a lista passa a ser uma lista de dicionários:
tarefas = [
{"titulo": "Pagar a conta de luz", "feita": True},
{"titulo": "Levar o Rex ao veterinário", "feita": False},
]
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
case "2":
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
case "3":
numero = int(input("Número da tarefa: "))
tarefa = tarefas[numero - 1]
tarefa["feita"] = True
print(f"Concluída: {tarefa['titulo']}")
case "4":
numero = int(input("Número da tarefa: "))
tarefa = tarefas.pop(numero - 1)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
| Linha | O que faz |
|---|---|
{"titulo": titulo, "feita": False} | A tarefa nova: o título digitado e "feita" valendo False (ainda não foi feita). |
marca = "x" if tarefa["feita"] else " " | Um if em uma linha: "x" para as feitas, espaço para as outras. Vira [x] ou [ ]. |
f"{numero}. [{marca}] {tarefa['titulo']}" | Dentro da f-string, a chave vai com aspas simples ('titulo'), porque a f-string já usa as duplas. (Desde o Python 3.12 dá para repetir as aspas duplas lá dentro, mas aspas diferentes funcionam em qualquer versão e são mais fáceis de ler.) |
numero = int(input("Número da tarefa: ")) | Aqui é preciso um número de verdade, para achar a tarefa na lista. |
tarefas[numero - 1] | A Ana conta a partir de 1; a lista, a partir de 0. A tarefa 2 da tela está na posição 1 da lista: por isso o - 1. |
tarefa["feita"] = True | Muda o valor da chave "feita" dentro do dicionário que está na lista. Não é preciso "devolver" a tarefa para a lista: a variável tarefa e a lista apontam para o mesmo dicionário (veja Mutável × Imutável). |
tarefas.pop(numero - 1) | Tira da lista o item daquela posição e o devolve, para o programa poder dizer qual foi removido (veja Removendo Itens). |
$ python3 tarefas.py === Lista de Tarefas da Ana === 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Comprar pão Tarefa adicionada: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Pagar a conta de luz Tarefa adicionada: Pagar a conta de luz 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Levar o Rex ao veterinário Tarefa adicionada: Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: 2 Concluída: Pagar a conta de luz 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 4 Número da tarefa: 1 Removida: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 2 1. [x] Pagar a conta de luz 2. [ ] Levar o Rex ao veterinário 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 0 Até mais!
Repare na última listagem: depois de remover a tarefa 1 (Comprar pão), as outras subiram uma posição. A conta de luz, que era a 2, virou a 1. Os números da tela são só a posição atual na lista.
Quando dá errado na versão 2
IndexError
$ python3 tarefas.py
=== Lista de Tarefas da Ana ===
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 1
Nova tarefa: Comprar pão
Tarefa adicionada: Comprar pão
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 3
Número da tarefa: 5
Traceback (most recent call last):
File "/home/ana/projetos/tarefas/tarefas.py", line 26, in <module>
tarefa = tarefas[numero - 1]
~~~~~~~^^^^^^^^^^^^
IndexError: list index out of range
Só existe a tarefa 1, e a Ana pediu a 5. IndexError: list index out of range = "erro de índice: a posição está fora da lista". A lista tem uma posição só (a 0), e o programa pediu a posição 4 (5 - 1). O sublinhado aponta o tarefas[numero - 1], na linha 26. Com pop, a mensagem seria parecida: IndexError: pop index out of range.
$ python3 tarefas.py
=== Lista de Tarefas da Ana ===
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 1
Nova tarefa: Comprar pão
Tarefa adicionada: Comprar pão
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 1
Nova tarefa: Pagar a conta de luz
Tarefa adicionada: Pagar a conta de luz
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 3
Número da tarefa: 0
Concluída: Pagar a conta de luz
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 2
1. [ ] Comprar pão
2. [x] Pagar a conta de luz
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 3
Número da tarefa: dois
Traceback (most recent call last):
File "/home/ana/projetos/tarefas/tarefas.py", line 25, in <module>
numero = int(input("Número da tarefa: "))
~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'dois'
Este é o pior tipo de defeito: o programa não reclamou, mas fez a coisa errada. A Ana digitou 0 e a última tarefa (a conta de luz) foi concluída. O motivo: 0 - 1 é -1, e, numa lista, o índice -1 é válido: quer dizer "o último item" (o -2 é o penúltimo, e assim por diante; veja Acessando Itens). Logo depois, o dois por extenso derrubou o programa com o ValueError que você já conhece da Calculadora. A versão 3 cuida dos três casos.
Missão (versão 2): o menu oferece "3 - Concluir tarefa", mas o match não tem o case "3", e a opção cai em "Opção inválida.". Escreva o caso: leia o número com int(input("Número da tarefa: ")), pegue a tarefa em tarefas[numero - 1], ponha True na chave "feita" e mostre Concluída: …. A entrada da missão cadastra duas tarefas, conclui a 2 e lista.
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
case "2":
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
case "4":
numero = int(input("Número da tarefa: "))
tarefa = tarefas.pop(numero - 1)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
case "2":
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
case "3":
numero = int(input("Número da tarefa: "))
tarefa = tarefas[numero - 1]
tarefa["feita"] = True
print(f"Concluída: {tarefa['titulo']}")
case "4":
numero = int(input("Número da tarefa: "))
tarefa = tarefas.pop(numero - 1)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
Versão 3 · Funções e número validado
O match estava ficando enorme. Na versão 3, cada pedaço com nome próprio vira uma função: mostrar_menu, listar e, a mais importante, escolher_tarefa, que pergunta o número e só devolve uma posição se ela existir. Concluir e remover usam a mesma função, então a validação é escrita uma vez só. E o título vazio (só Enter) passa a ser recusado.
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
- def escolher_tarefa(tarefas):
- Recebe a lista e devolve a posição da tarefa escolhida (de 0 em diante), ou
Nonequando não dá. - if not tarefas: … return None
- Lista vazia: nem pergunta.
- if not texto.isdigit():
isdigit()("é dígito?") dáTruesó se o texto tiver apenas algarismos. Recusa"dois",""e também"-1"(o sinal de menos não é algarismo).- if not 1 <= numero <= len(tarefas):
- O número tem de estar entre 1 e a quantidade de tarefas. É aqui que o
0e o5são barrados. - return numero - 1
- A conversão "número da tela → posição na lista" agora mora num lugar só.
- if posicao is not None:
- No programa principal: só conclui ou remove se veio uma posição. Atenção:
if posicao:estaria errado, porque a posição 0 (a primeira tarefa) conta como falso. ParaNone, use sempreis/is not. - if titulo:
- Texto vazio conta como falso: recusa o título vazio.
$ python3 Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> "12".isdigit() True >>> "-1".isdigit() False >>> " 3".isdigit() False >>> exit()
O espaço também conta: " 3".isdigit() é False. Por isso o texto passa pelo strip() antes do teste.
$ python3 tarefas.py === Lista de Tarefas da Ana === 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Nenhuma tarefa ainda. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: A tarefa precisa de um nome. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Comprar pão Tarefa adicionada: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: 5 Não existe a tarefa 5. Escolha de 1 a 1. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: 0 Não existe a tarefa 0. Escolha de 1 a 1. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: dois "dois" não é um número. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 3 Número da tarefa: 1 Concluída: Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 2 1. [x] Comprar pão 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 0 Até mais!
KeyError
Com dicionários, um erro de digitação no nome da chave não passa despercebido:
$ python3
Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> tarefa = {"titulo": "Comprar pão", "feita": False}
>>> tarefa["titlo"]
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
tarefa["titlo"]
~~~~~~^^^^^^^^^
KeyError: 'titlo'
>>> exit()
KeyError: 'titlo' = "erro de chave: não existe a chave 'titlo'". (No modo interativo, o "arquivo" se chama <python-input-1>: é a segunda entrada digitada nessa sessão, contando a partir de 0.) Como consertar: confira o nome da chave, letra por letra. Num programa grande, o mesmo erro aparece com o nome do arquivo e a linha.
Missão (versão 3): a função escolher_tarefa ainda não valida nada, e o 5 da entrada derruba o programa com IndexError. Escreva o corpo dela como na versão 3: lista vazia, isdigit() e o teste 1 <= numero <= len(tarefas) com a mensagem Não existe a tarefa 5. Escolha de 1 a 1. A entrada da missão cadastra uma tarefa, tenta concluir a 5, depois a 0, depois a 1, e lista.
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
return int(input("Número da tarefa: ")) - 1
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
tarefas = []
print("=== Lista de Tarefas da Ana ===")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
Versão 4 · Guardar num arquivo
Até a versão 3, tudo o que a Ana cadastra some quando o programa fecha: a lista vive na memória do computador só enquanto o programa roda. Para as tarefas sobreviverem, a versão 4 as grava num arquivo de texto, tarefas.txt, uma por linha, no mesmo formato da tela:
[ ] Comprar pão [x] Pagar a conta de luz [ ] Levar o Rex ao veterinário
Duas funções novas: carregar(), que lê o arquivo quando o programa abre, e salvar(tarefas), chamada depois de cada mudança (adicionar, concluir, remover). O resto é a versão 3.
ARQUIVO = "tarefas.txt"
def carregar():
"""Lê as tarefas do arquivo. Se ele ainda não existe, começa com a lista vazia."""
tarefas = []
try:
with open(ARQUIVO, encoding="utf-8") as arquivo:
for linha in arquivo:
linha = linha.rstrip("\n")
if linha.startswith("[x] "):
tarefas.append({"titulo": linha[4:], "feita": True})
elif linha.startswith("[ ] "):
tarefas.append({"titulo": linha[4:], "feita": False})
except FileNotFoundError:
pass # primeira vez: ainda não há arquivo
return tarefas
def salvar(tarefas):
"""Grava todas as tarefas no arquivo, uma por linha."""
with open(ARQUIVO, "w", encoding="utf-8") as arquivo:
for tarefa in tarefas:
marca = "x" if tarefa["feita"] else " "
arquivo.write(f"[{marca}] {tarefa['titulo']}\n")
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
print("=== Lista de Tarefas da Ana ===")
tarefas = carregar()
print(f"{len(tarefas)} tarefa(s) carregada(s) de {ARQUIVO}.")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
salvar(tarefas)
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
salvar(tarefas)
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
salvar(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
| Peça | O que faz |
|---|---|
open(ARQUIVO, "w", encoding="utf-8") | Abre para escrever ("w", de write). Atenção: o "w" apaga o que havia no arquivo e começa do zero. Aqui é o que queremos: a cada salvar, o arquivo recebe a lista inteira, atualizada (veja Escrevendo Arquivos). |
arquivo.write(f"[{marca}] …\n") | Escreve uma linha. O write não pula linha sozinho, como o print: o \n no fim é obrigatório. |
with open(ARQUIVO, encoding="utf-8") as arquivo: | Sem o "w", abre para ler (o padrão). O with fecha o arquivo no fim do bloco. |
linha.rstrip("\n") | Tira só o \n do fim da linha (o r é de right, "direita"). Um strip() comum também tiraria espaços que façam parte do título. |
linha.startswith("[x] ") | "Começa com?": decide se a tarefa estava feita. |
linha[4:] | Uma fatia: tudo a partir da posição 4, ou seja, o texto depois de [x] (quatro caracteres: colchete, x, colchete, espaço). |
except FileNotFoundError: pass | Na primeira vez, o arquivo ainda não existe, e o open daria FileNotFoundError. Aqui isso não é um problema: começa com a lista vazia. O pass ("passar") é a instrução que não faz nada. |
As duas sessões do começo da página são desta versão: na primeira, o programa diz 0 tarefa(s) carregada(s) (o arquivo ainda não existia) e, ao sair, o tarefas.txt já tem as três tarefas; na segunda, ele carrega as três, e a remoção também vai para o arquivo.
Se o programa fosse interrompido no meio (um Ctrl+C, um erro, a bateria do notebook), tudo o que a Ana fez desde que abriu o programa se perderia. Salvando a cada mudança, o arquivo está sempre em dia. Com poucas tarefas, regravar o arquivo inteiro é instantâneo.
Quando dá errado na versão 4
"a" no lugar de "w": as tarefas se duplicam
O modo "a" (de append, "acrescentar") escreve no fim do arquivo, sem apagar o que já havia. Parece mais seguro, mas olhe o que acontece com a função salvar, que grava a lista inteira:
$ python3 tarefas.py === Lista de Tarefas da Ana === 2 tarefa(s) carregada(s) de tarefas.txt. 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 1 Nova tarefa: Regar as plantas Tarefa adicionada: Regar as plantas 1 - Adicionar tarefa 2 - Ver tarefas 3 - Concluir tarefa 4 - Remover tarefa 0 - Sair Escolha: 0 Até mais! $ cat tarefas.txt [x] Pagar a conta de luz [ ] Levar o Rex ao veterinário [x] Pagar a conta de luz [ ] Levar o Rex ao veterinário [ ] Regar as plantas
O arquivo tinha 2 tarefas; o programa carregou as 2, a Ana acrescentou uma, e o salvar escreveu as 3 depois das 2 que já estavam lá: 5 linhas, com repetições. Na próxima vez, seriam 5 carregadas, e o arquivo cresceria a cada mudança. Não há traceback, porque para o Python está tudo certo. Como consertar: quando a função grava a lista inteira, use "w".
io.UnsupportedOperation: not writable
$ python3 tarefas.py
=== Lista de Tarefas da Ana ===
5 tarefa(s) carregada(s) de tarefas.txt.
1 - Adicionar tarefa
2 - Ver tarefas
3 - Concluir tarefa
4 - Remover tarefa
0 - Sair
Escolha: 1
Nova tarefa: Lavar a louça
Tarefa adicionada: Lavar a louça
Traceback (most recent call last):
File "/home/ana/projetos/tarefas/tarefas.py", line 75, in <module>
salvar(tarefas)
~~~~~~^^^^^^^^^
File "/home/ana/projetos/tarefas/tarefas.py", line 25, in salvar
arquivo.write(f"[{marca}] {tarefa['titulo']}\n")
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
io.UnsupportedOperation: not writable
Sem o "w", o open abriu o arquivo só para leitura, e o write falhou: io.UnsupportedOperation: not writable = "operação não suportada: (o arquivo) não aceita escrita". O traceback tem dois trechos: o programa principal chamou salvar na linha 75, e dentro dela o write da linha 25 deu o erro. (Repare que o programa chegou a dizer "Tarefa adicionada", mas não conseguiu gravar.) Como consertar: open(ARQUIVO, "w", encoding="utf-8").
Missão (versão 4, salvar): a função salvar ainda não faz nada, e o tarefas.txt nunca é criado. Escreva o corpo dela: abra o arquivo com "w" e encoding="utf-8" e, para cada tarefa, grave [x] título ou [ ] título com \n no fim. A entrada da missão cadastra duas tarefas e conclui a primeira; a missão confere o arquivo tarefas.txt depois que o programa termina.
ARQUIVO = "tarefas.txt"
def carregar():
"""Lê as tarefas do arquivo. Se ele ainda não existe, começa com a lista vazia."""
tarefas = []
try:
with open(ARQUIVO, encoding="utf-8") as arquivo:
for linha in arquivo:
linha = linha.rstrip("\n")
if linha.startswith("[x] "):
tarefas.append({"titulo": linha[4:], "feita": True})
elif linha.startswith("[ ] "):
tarefas.append({"titulo": linha[4:], "feita": False})
except FileNotFoundError:
pass # primeira vez: ainda não há arquivo
return tarefas
def salvar(tarefas):
"""Grava todas as tarefas no arquivo, uma por linha."""
pass # escreva aqui: abra o arquivo com "w" e grave uma linha por tarefa
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
print("=== Lista de Tarefas da Ana ===")
tarefas = carregar()
print(f"{len(tarefas)} tarefa(s) carregada(s) de {ARQUIVO}.")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
salvar(tarefas)
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
salvar(tarefas)
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
salvar(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
ARQUIVO = "tarefas.txt"
def carregar():
"""Lê as tarefas do arquivo. Se ele ainda não existe, começa com a lista vazia."""
tarefas = []
try:
with open(ARQUIVO, encoding="utf-8") as arquivo:
for linha in arquivo:
linha = linha.rstrip("\n")
if linha.startswith("[x] "):
tarefas.append({"titulo": linha[4:], "feita": True})
elif linha.startswith("[ ] "):
tarefas.append({"titulo": linha[4:], "feita": False})
except FileNotFoundError:
pass # primeira vez: ainda não há arquivo
return tarefas
def salvar(tarefas):
"""Grava todas as tarefas no arquivo, uma por linha."""
with open(ARQUIVO, "w", encoding="utf-8") as arquivo:
for tarefa in tarefas:
marca = "x" if tarefa["feita"] else " "
arquivo.write(f"[{marca}] {tarefa['titulo']}\n")
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
print("=== Lista de Tarefas da Ana ===")
tarefas = carregar()
print(f"{len(tarefas)} tarefa(s) carregada(s) de {ARQUIVO}.")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
salvar(tarefas)
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
salvar(tarefas)
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
salvar(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
Na caixa abaixo, o tarefas.txt já existe, numa aba ao lado do programa: é o arquivo que a Ana deixou ontem.
Missão (versão 4, carregar): agora o contrário: a função carregar não lê o arquivo, e o programa diz 0 tarefa(s) carregada(s) mesmo com o tarefas.txt da aba. Escreva a leitura como na versão 4 (com try, with open, startswith e linha[4:], e o except FileNotFoundError). A entrada da missão só lista e sai.
ARQUIVO = "tarefas.txt"
def carregar():
"""Lê as tarefas do arquivo. Se ele ainda não existe, começa com a lista vazia."""
tarefas = []
# escreva aqui: leia o arquivo e acrescente cada tarefa na lista
return tarefas
def salvar(tarefas):
"""Grava todas as tarefas no arquivo, uma por linha."""
with open(ARQUIVO, "w", encoding="utf-8") as arquivo:
for tarefa in tarefas:
marca = "x" if tarefa["feita"] else " "
arquivo.write(f"[{marca}] {tarefa['titulo']}\n")
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
print("=== Lista de Tarefas da Ana ===")
tarefas = carregar()
print(f"{len(tarefas)} tarefa(s) carregada(s) de {ARQUIVO}.")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
salvar(tarefas)
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
salvar(tarefas)
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
salvar(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
[x] Pagar a conta de luz [ ] Levar o Rex ao veterinário
ARQUIVO = "tarefas.txt"
def carregar():
"""Lê as tarefas do arquivo. Se ele ainda não existe, começa com a lista vazia."""
tarefas = []
try:
with open(ARQUIVO, encoding="utf-8") as arquivo:
for linha in arquivo:
linha = linha.rstrip("\n")
if linha.startswith("[x] "):
tarefas.append({"titulo": linha[4:], "feita": True})
elif linha.startswith("[ ] "):
tarefas.append({"titulo": linha[4:], "feita": False})
except FileNotFoundError:
pass # primeira vez: ainda não há arquivo
return tarefas
def salvar(tarefas):
"""Grava todas as tarefas no arquivo, uma por linha."""
with open(ARQUIVO, "w", encoding="utf-8") as arquivo:
for tarefa in tarefas:
marca = "x" if tarefa["feita"] else " "
arquivo.write(f"[{marca}] {tarefa['titulo']}\n")
def mostrar_menu():
print()
print("1 - Adicionar tarefa")
print("2 - Ver tarefas")
print("3 - Concluir tarefa")
print("4 - Remover tarefa")
print("0 - Sair")
def listar(tarefas):
"""Mostra as tarefas numeradas a partir de 1, com [x] nas feitas."""
if not tarefas:
print("Nenhuma tarefa ainda.")
for numero, tarefa in enumerate(tarefas, start=1):
marca = "x" if tarefa["feita"] else " "
print(f"{numero}. [{marca}] {tarefa['titulo']}")
def escolher_tarefa(tarefas):
"""Pergunta o número de uma tarefa e devolve a posição dela na lista (ou None)."""
if not tarefas:
print("Nenhuma tarefa ainda.")
return None
texto = input("Número da tarefa: ").strip()
if not texto.isdigit():
print(f'"{texto}" não é um número.')
return None
numero = int(texto)
if not 1 <= numero <= len(tarefas):
print(f"Não existe a tarefa {numero}. Escolha de 1 a {len(tarefas)}.")
return None
return numero - 1
print("=== Lista de Tarefas da Ana ===")
tarefas = carregar()
print(f"{len(tarefas)} tarefa(s) carregada(s) de {ARQUIVO}.")
while True:
mostrar_menu()
opcao = input("Escolha: ").strip()
match opcao:
case "1":
titulo = input("Nova tarefa: ").strip()
if titulo:
tarefas.append({"titulo": titulo, "feita": False})
print(f"Tarefa adicionada: {titulo}")
salvar(tarefas)
else:
print("A tarefa precisa de um nome.")
case "2":
listar(tarefas)
case "3":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefas[posicao]["feita"] = True
print(f"Concluída: {tarefas[posicao]['titulo']}")
salvar(tarefas)
case "4":
posicao = escolher_tarefa(tarefas)
if posicao is not None:
tarefa = tarefas.pop(posicao)
print(f"Removida: {tarefa['titulo']}")
salvar(tarefas)
case "0":
print("Até mais!")
break
case _:
print("Opção inválida.")
Formas diferentes de fazer
Validar o número: isdigit() ou try/except
A versão 3 testou o texto antes de converter. A Calculadora fez o contrário: tentou converter e tratou o erro. As duas funcionam aqui:
try:
numero = int(texto)
except ValueError:
print(f'"{texto}" não é um número.')
return None
| Forma | Quando usar |
|---|---|
texto.isdigit() antes do int() | Números inteiros sem sinal, como o número de uma tarefa. Fácil de ler: "se não for só algarismos…". |
try: int(texto) / except ValueError | Quando o número pode ter sinal ou casas decimais ("-3", "2.5" com float). É o jeito mais comum em Python: "tente, e trate se der errado". |
Onde guardar as tarefas
| Forma | Quando usar |
|---|---|
Texto, uma linha por item ([x] Comprar pão) | Dados simples. Dá para abrir e editar o arquivo à mão. Foi a escolha deste projeto. |
| CSV | Várias colunas por item (título, data, prioridade), e o arquivo abre numa planilha. |
| JSON | Grava listas e dicionários do Python quase como estão, sem você inventar um formato. É o que o próximo projeto, a Agenda de Contatos, usa. |
| Banco de dados (sqlite3) | Muitos dados, buscas e mudanças frequentes. |
Ideias para continuar
- Uma opção "5 - Ver só as pendentes", com um
forque pule as feitas (ou uma list comprehension). - Editar o título de uma tarefa (use
escolher_tarefade novo). - Mostrar no fim da listagem quantas faltam:
3 tarefa(s), 1 feita(s). - Um título com
[x]no começo confunde ocarregar? Experimente cadastrar a tarefa[x] testee abrir o programa de novo.
Referência rápida do projeto
| Escrita | Para que serviu |
|---|---|
while True: + match opcao: | O menu que se repete até a opção de sair |
tarefas.append(item) | Acrescentar no fim da lista |
enumerate(tarefas, start=1) | Numerar a partir de 1 ao percorrer |
{"titulo": t, "feita": False} | Uma tarefa com duas informações |
tarefas[numero - 1]["feita"] = True | Concluir: número da tela → posição da lista; mudar a chave |
tarefas.pop(posicao) | Remover e receber o item removido |
texto.isdigit(), 1 <= numero <= len(tarefas) | Validar o número escolhido |
if posicao is not None: | Conferir se a função devolveu uma posição (a 0 também é válida) |
open(nome, "w", encoding="utf-8") + write(… + "\n") | Gravar o arquivo do zero |
try: open(nome) … except FileNotFoundError: | Ler o arquivo, se ele existir |
linha.rstrip("\n"), linha.startswith("[x] "), linha[4:] | Desmontar cada linha do arquivo |
| Sintoma | Causa provável |
|---|---|
IndexError: list index out of range | Número de tarefa maior que a lista: valide antes |
| O 0 conclui (ou remove) a última tarefa | 0 - 1 é -1, o último item: exija numero >= 1 |
ValueError: invalid literal for int() … | Texto que não é número no int() |
KeyError: 'titlo' | Nome da chave do dicionário escrito errado |
| A primeira tarefa nunca é concluída | if posicao: no lugar de if posicao is not None: (a posição 0 conta como falso) |
| As tarefas se repetem no arquivo | Modo "a" numa função que grava a lista inteira: use "w" |
io.UnsupportedOperation: not writable | open sem o "w" |
| As tarefas somem ao fechar o programa | Faltou chamar salvar (ou ele grava num arquivo e o carregar lê outro) |
Exercícios
1. Numerar a partir de 1
Complete:
2. Remover e receber
Complete o método que tira a tarefa da posição posicao e a devolve:
3. O modo de escrita
Complete o modo que apaga o arquivo e escreve do zero:
4. Na versão 2, a Ana digitou 0 como número da tarefa. O que aconteceu?
5. Por que o programa principal da versão 3 usa if posicao is not None: e não if posicao:?
6. Na primeira vez que a versão 4 roda, o tarefas.txt não existe. O que acontece?
Resumo
- Um programa de menu é um
while Trueque mostra as opções, lê a escolha (como texto) e usamatch; obreaksó no "sair". - A lista fica fora do laço.
appendacrescenta,pop(posição)remove e devolve. - A tela conta a partir de 1, a lista a partir de 0:
enumerate(…, start=1)para mostrar,numero - 1para achar. - O índice
-1é válido (o último item): um 0 digitado vira-1e erra calado. Valide com1 <= numero <= len(lista). - Um item com várias informações vira um dicionário; mudar a chave muda o item que está na lista.
- Para os dados sobreviverem, grave num arquivo:
"w"regrava tudo,"a"acrescenta no fim. Leia comtrye trate oFileNotFoundErrorda primeira vez.