CSE 111: Programação com Funções

S05 - Atividade de Aprendizagem (2 de 2): Exceções

Erros e situações excepcionais às vezes ocorrem enquanto um programa está em execução. Esses erros incluem, por exemplo, tentar ler um arquivo que não existe, um erro de conexão ao se conectar a um servidor na rede, dados que não podem ser encontrados em um servidor e cálculos que produzem resultados indefinidos. Um programa bem escrito não falha quando ocorre um erro; em vez disso, ele o trata de forma apropriada, o que pode incluir ajustar-se à situação, exibir uma mensagem de erro para o usuário e salvar a mensagem de erro em um arquivo de log. Durante esta lição, você aprenderá a escrever código que trata erros que podem ocorrer enquanto seu programa Python está em execução.

Vídeos

Assista a este vídeo sobre tratamento de erros e exceções:

Conceitos

Aqui estão os conceitos e assuntos de programação em Python que você deve aprender durante esta aula.

O que é uma Exceção?

Uma exceção é um evento relativamente raro que pode ocorrer quando um programa está em execução. Por exemplo, uma exceção ocorre quando um programa Python tenta abrir e ler um arquivo, mas esse arquivo não existe. Há diferentes exceções embutidas que podem ocorrer enquanto um programa Python está em execução.

Quando ocorre um evento excepcional, uma função em Python gera uma exceção, que pode ser tratada por um código em outro ponto do programa em execução. A palavra-chave em Python para gerar uma exceção é raise. Normalmente, você não precisará escrever código para gerar exceções, pois funções internas como open, int e float já farão isso automaticamente quando necessário. Contudo, será preciso escrever código nos seus programas para lidar com essas exceções.

Como lidar com uma Exceção

As palavras-chave de Python para lidar com exceções são try, except, else e finally. O código de exemplo a seguir contém o esboço de um bloco try-except-else-finally completo. Leia o código e seus comentários cuidadosamente para entender a sintaxe e a organização corretas de um bloco try-except-else-finally.

# Exemplo 1
try:
    # Código normal aqui.
    # Inclua:
    # 1. Instruções que podem gerar uma exceção
    # 2. Instruções que dependem dos resultados anteriores

except ZeroDivisionError as err_de_div_por_zero:
    # Executado se ocorrer ZeroDivisionError

except ValueError as err_de_valor:
    # Executado se ocorrer ValueError

except (TypeError, KeyError, IndexError) as error:
    # Executado se ocorrer TypeError, KeyError ou IndexError

except Exception as excep:
    # Executado se ocorrer uma exceção não tratada acima

except:
    # Executado se ocorrer algo não tratado por nenhum except anterior

else:
    # Executado se NENHUMA exceção ocorrer no bloco try

finally:
    # Executado sempre, independentemente de erro ou sucesso

Como mostrado no exemplo 1 acima, quando queremos escrever código que processará exceções, primeiro escrevemos um bloco try e colocamos o código normal que pode causar uma exceção nesse bloco try. Então escrevemos blocos except para lidar com as exceções. Cada bloco except pode lidar com um tipo de exceção, como o código na linha  8:

except ZeroDivisionError as err_de_div_por_zero:

Ou cada bloco except pode lidar com vários tipos de exceções, como o código na linha 14:

except (TypeError, KeyError, IndexError) as error:

Ou um bloco except pode lidar com todos os tipos possíveis de exceções, como o código na linha 18:

except Exception as excep:

Ou um bloco except simples pode capturar qualquer exceção gerada, incluindo SystemExit, KeyboardInterrupt e GeneratorExit, como o código na linha 22:

except:

A linguagem Python exige que ordenemos os blocos except do mais específico na parte superior para o menos específico (mais geral) na parte inferior.

Em um programa Python, geralmente é uma má ideia escrever um bloco except simples (linha 22), pois um bloco except simples lidará com KeyboardInterrupt e SystemExit. Escrever código para processar KeyboardInterrupt, inclusive um bloco except simples, pode dificultar que o usuário saia do programa. O motivo mais comum para escrever blocos try e except é escrever código que permitirá que um programa se recupere de um erro. Escrever código de recuperação é mais fácil em um bloco except com o tipo de exceção, como os blocos except nas linhas 8, 11 e 14 . É por isso que programadores profissionais raramente escrevem blocos except vazios.

Conforme mostrado na linha 26 do exemplo 1 acima, após os blocos except, um programador pode escrever um bloco else opcional que o computador executará se o bloco try não gerar nenhuma exceção. Contudo, não é comum escrever um bloco else para blocos try e except, porque qualquer código que poderia ser escrito em um bloco else de try e except também poderia ser escrito no final do bloco try. Programadores profissionais quase nunca escrevem um bloco else para os blocos try e except.

Conforme mostrado na linha 30 do exemplo 1 acima, no final do código de tratamento de exceção, um programador pode escrever um bloco finally opcional. O bloco finally contém código que o computador executa depois de todos os outros códigos nos blocos try, except e else, independentemente da geração de uma exceção. Em geral, o código no bloco finally contém código de “limpeza” que libera recursos que o código no bloco try usou. Por exemplo, se o código no bloco try abrir um arquivo, o código no bloco finally poderá fechar esse arquivo. No CSE 111, você não precisará escrever um bloco finally.

Em resumo, no CSE 111 você precisará usar blocos try e except para tratar exceções, mas não será necessário incluir os blocos else ou finally.

Tipos Comuns de Exceções

Existem muitos tipos diferentes de exceções embutidas que podem ocorrer enquanto um programa Python está em execução. Esta seção mostra como sete tipos de exceções podem ocorrer.

TypeError

O computador gera um TypeError quando o código que chama uma função passa um argumento com o tipo de dado errado. O código no exemplo 2 tenta passar uma string para a função round. Isso faz com que o computador gere um TypeError, já que a função round não consegue arredondar uma string para um inteiro, apenas um número para um inteiro. A saída abaixo do exemplo 2 mostra que o computador gerou um TypeError.

# Exemplo 2
def main():
  try:
    texto = input("Por favor, digite um número: ")
    inteiro = round(texto)
    print(inteiro)
  except TypeError as err_de_tipo:
    print(err_de_tipo)
if __name__ == "__main__":
  main()
> python err_de_tipo.py
Por favor, digite um número: 25.7
type str doesn't define __round__ method

Tradução: o tipo str não possui o método __round__

ValueError

O computador gera um ValueError quando o código que chama uma função passa um argumento com o tipo de dado correto, mas com um valor inválido. Um evento comum que faz com que o computador gere um ValueError é quando a função int ou float tenta converter uma string em um número, mas a string contém caracteres que não são dígitos. O código no exemplo 3 e sua saída mostram um ValueError.

# Exemplo 3
def main():
  try:
    numero = float(input("Por favor, digite um número: "))
    print(numero)
  except ValueError as err_de_valor:
    print(err_de_valor)
if __name__ == "__main__":
  main()
> python erro_valor.py
Por favor, digite um número: 45.7u
could not convert string to float: '45.7u'

Tradução: não foi possível converter string em float: '45.7u'

ZeroDivisionError

O computador gera um ZeroDivisionError quando um programa tenta dividir um número por 0 (zero), conforme mostrado no exemplo 4 e sua saída.

# Exemplo 4
def main():
  try:
    jogadores = int(input("Digite o número de jogadores: "))
    equipes = int(input("Digite o número de equipes: "))
    jogadores_por_equipe = jogadores / equipes
    print(f"Cada equipe deve ter {jogadores_por_equipe} jogadores")
  except ZeroDivisionError as err_de_div_por_zero:
    print(err_de_div_por_zero)
if __name__ == "__main__":
  main()
> python err_de_div_por_zero.py
Digite o número de jogadores: 20
Digite o número de equipes: 0
division by zero

Tradução: divisão por zero

IndexError

Lembre-se da semana 4: cada elemento em uma lista é armazenado em um índice exclusivo e um índice é sempre um inteiro. Se escrevermos um código que tenta usar um índice que não existe em uma lista, quando o computador executar esse código, ele gerará um IndexError. O programa no exemplo 5 cria uma lista que contém três sobrenomes. Em seguida, o programa tenta alterar o sobrenome no índice 3. Claro, a lista contém apenas três elementos, e o índice do último elemento é 2, então a instrução falha e faz com que o computador gere um IndexError.

# Exemplo 5
def main():
  try:
    # Cria uma lista que contenha três sobrenomes.
    sobrenomes = ["Silva", "Lopes", "Peixoto"]
    # Esse código tenta alterar o sobrenome no índice 3. Como
    # existem apenas três nomes na lista de sobrenomes e
    # o último índice é 2, esta instrução falhará e
    # fará com que o computador gere um IndexError.
    sobrenomes[3] = "Freitas"
  except IndexError as err_de_indice:
    print(err_de_indice)
if __name__ == "__main__":
  main()
> python escrever_erro_de_indice.py
list assignment index out of range

Tradução: índice de atribuição de lista fora do intervalo

O programa no exemplo 6 é semelhante ao exemplo 5, e ambos os programas fazem com que o computador gere um IndexError. O programa do exemplo 6 cria uma lista com três sobrenomes. Em seguida, ele tenta exibir o sobrenome no índice 3. O erro acontece porque, em uma lista com três elementos, o último índice válido é 2. Para que o índice 3 existisse e a atribuição fosse bem-sucedida, a lista precisaria ter pelo menos quatro elementos. Caso não tenha entendido o motivo do erro, veja essa explicação.

# Exemplo 6
def main():
  try:
    # Cria uma lista que contenha três sobrenomes.
    sobrenomes = ["Silva", "Lopes", "Peixoto"]
    # Esse código tenta exibir o sobrenome no índice 3. Como
    # existem apenas três nomes na lista de sobrenomes e
    # o último índice é 2, esta instrução falhará e
    # fará com que o computador gere um IndexError.
    print(sobrenomes[3])
  except IndexError as err_de_indice:
    print(err_de_indice)
if __name__ == "__main__":
  main()
> python ler_erro_de_indice.py
list index out of range

Tradução: índice da lista fora do intervalo

KeyError

A exceção KeyError ocorre quando tentamos acessar uma chave que não existe em um dicionário, como mostrado no exemplo a seguir.

# Exemplo 7
def main():
  try:
    # Cria um dicionário com identificações de estudantes como
    # as chaves e os nomes dos estudantes como valores.
    estudantes = {
      "42-039-4736": "Carlos Silva",
      "61-315-0160": "Maria Oliveira",
      "10-450-1203": "Ana Soares",
      "75-421-2310": "João Pereira",
      "07-103-5621": "Maria Oliveira"
    }
    # Esse código tenta encontrar a chave "50-420-1021",
    # que não está no dicionário. Isto fará
    # com que o computador gere um KeyError.
    nome = estudantes["50-420-1021"]
    print(nome)
  except KeyError as err_de_chave:
    print(type(err_de_chave).__name__, err_de_chave)
if __name__ == "__main__":
  main()
> python err_de_chave.py
KeyError '50-420-1021'

Tradução: Erro de chave: '50-420-1021'

É muito improvável que um programador busque uma chave que não esteja no dicionário. Entretanto, é comum que um usuário procure por uma chave inexistente, o que gera um KeyError. Para evitar esse erro, podemos incluir uma instrução if para verificar se a chave a ser procurada existe no dicionário.

A título de exemplo, você pode verificar o código a seguir, bem como o exemplo 1 e o exemplo 4 do conteúdo de preparação sobre dicionários da Semana 4.

# Obtenha uma identificação de estudante do usuário.
id = input("Digite uma identificação de estudante: ")
# Verifica se a identificação do estudante está no dicionário.
if id in estudantes:
  # Encontra a identificação do estudante no dicionário e
  # recupera o nome do estudante correspondente.
  nome = estudantes[id]
  # Exibe o nome do estudante.
  print(nome)
else:
  print("Estudante inexistente")

FileNotFoundError

A exceção FileNotFoundError ocorre quando usamos a função open para tentar abrir um arquivo para leitura e ele não existe ou não foi encontrado. O exemplo 8 mostra um código em que esse erro pode ocorrer.

# Exemplo 8
def main():
  try:
    with open("produtos.vcs", "rt", encoding="utf-8") as arquivo_de_produtos:
      for linha in arquivo_de_produtos:
        print(linha)
  except FileNotFoundError as err_nao_encontrado:
    print(err_nao_encontrado)
if __name__ == "__main__":
  main()
> python arquivo_nao_encontrado.py
[Errno 2] No such file or directory: 'produtos.vcs'

Tradução: [Errno 2] Nenhum arquivo ou diretório: 'produtos.vcs'

PermissionError

Quase todos os sistemas operacionais de computador, como Microsoft Windows, macOS e Linux, permitem que várias pessoas usem um único computador. Como as pessoas precisam armazenar dados privados em arquivos em um computador, os sistemas operacionais implementam regras de permissão de acesso a arquivos. Essas regras ajudam a evitar acesso não autorizado aos arquivos.

Se escrevermos uma chamada para a função open que tenta abrir um arquivo e a pessoa que executa nosso programa não tem permissão para acessá-lo, o computador gerará um PermissionError. O exemplo 9 contém código onde esse erro pode ocorrer.

# Exemplo 9
def main():
  try:
    with open("contatos.csv", "rt") as arquivo_de_contatos:
      for linha in arquivo_de_contatos:
        print(linha)
  except PermissionError as err_de_perm:
    print(err_de_perm)
if __name__ == "__main__":
  main()
> python erro_de_permissao.py
[Errno 13] Permission denied: 'contatos.csv'

Tradução: [Errno 13] Permissão negada: 'contatos.csv'

Exemplo: Aritmética

O exemplo 10 contém um programa completo com blocos except para lidar com dois tipos de exceções: ValueError e ZeroDivisionError.

# Exemplo 10
"""
O dono da Sanduicheria País Tropical pediu um programa
para calcular quantos sanduíches cada funcionário
preparou no restaurante em um dia.
"""
def main():
  try:
    # Solicita ao usuário o número de sanduíches preparados hoje e o
    # número de funcionários que trabalharam hoje.
    sanduiches = int(input("Número de sanduíches feitos hoje: "))
    funcionarios = int(input("Número de funcionarios que trabalharam hoje: "))
    # Calcula o número de sanduíches por funcionário
    # que foram preparados no restaurante hoje.
    sands_por_func = sanduiches / funcionarios
    # Exibe os resultados para o usuário.
    print(f"{sands_por_func:.1f} sanduíches por funcionário")
  except ValueError as err_de_valor:
    print(f"Erro: {err_de_valor}")
    print("Você não inseriu um número inteiro. Por favor,")
    print("execute o programa novamente e insira um número inteiro.")
  except ZeroDivisionError as err_de_div_por_zero:
    print(f"Erro: {err_de_div_por_zero}")
    print("Você digitou 0 para o número de funcionários.")
    print("Por favor, execute o programa novamente e insira um número inteiro")
    print("maior que 0 para o número de funcionários.")
    # Chama main para iniciar este programa.
if __name__ == "__main__":
  main()
> python exemplo_10.py
Número de sanduíches feitos hoje: 35u
Erro: invalid literal for int() with base 10: '35u'
Tradução: Erro: literal inválido para int() com base 10: '35u'
Você não inseriu um número inteiro. Por favor,
execute o programa novamente e insira um número inteiro.

> python exemplo_10.py
Número de sanduíches preparados hoje: 350.4
Erro: invalid literal for int() with base 10: '350.4'
Tradução: Erro: literal inválido para int() com base 10: '350.4'
Você não inseriu um número inteiro. Por favor,
execute o programa novamente e insira um número inteiro.

> python exemplo_10.py
Número de sanduíches feitos hoje: 350
Número de funcionários que trabalharam hoje: 0
Erro: division by zero
Tradução: Erro: divisão por zero
Você digitou 0 para o número de funcionários.
Por favor, execute o programa novamente e insira um número inteiro.
maior que 0 para o número de funcionários.

> python exemplo_10.py
Número de sanduíches feitos hoje: 350
Número de funcionários que trabalharam hoje: 8
43.8 sanduíches por funcionário

Exemplo: Lendo de um Arquivo

O programa no exemplo 11 abaixo lida com exceções que podem ocorrer quando ele abre e lê um arquivo. Este programa contém apenas um bloco try, que começa na linha  8 e inclui todo o código regular na função main. O bloco try tem três blocos except nas linhas 36, 38 e 40, os quais processam FileNotFoundError, PermissionError e ZeroDivisionError.

# Exemplo 11
import csv
INDICE_DE_DATA = 0
INDICE_DE_MILHAS_INICIAIS = 1
INDICE_DE_MILHAS_FINAIS = 2
INDICE_DE_GALOES = 3
def main():
  try:
    # Abre o arquivo consumo_de_combustivel.csv.
    filename= "consumo_de_combustivel.csv"
    with open(filename, "rt", encoding="utf-8") as arquivo_de_consumo:
    # Usa o módulo csv padrão para obter
    # um objeto leitor para o arquivo CSV.
    leitor = csv.reader(arquivo_de_consumo)
    # A primeira linha do arquivo CSV contém
    # títulos e não dados de consumo de combustível, então esta
    # instrução ignora a primeira linha do arquivo.
    next(leitor)
    # Exibe cabeçalhos das três colunas.
    print("Data,Início,Fim,Galões,Milhas/Galão")
    # Processa cada linha no arquivo CSV.
    for lista_de_linhas in leitor:
    # Da linha atual do arquivo CSV, obtenha
    # a data, a leitura inicial e a final do odômetro 
    # o número de galões consumidos.
    data = lista_de_linhas[INDICE_DE_DATA]
    milhas_iniciais = float(lista_de_linhas[INDICE_DE_MILHAS_INICIAIS])
    milhas_finais = float(lista_de_linhas[INDICE_DE_MILHAS_FINAIS])
    galoes = float(lista_de_linhas[INDICE_DE_GALOES])
    # Chama a função milhas_por_galao.
    mpg = milhas_por_galao(
    milhas_iniciais, milhas_finais, galoes)
    # Exibe os resultados de uma linha.
    mpg = round(mpg, 1)
    print(data, milhas_iniciais, milhas_finais, galoes, mpg, sep=",")
  except FileNotFoundError as err_nao_encontrado:
    print(f"Erro: não é possível abrir {filename}. Ele não existe.")
  except PermissionError as err_de_perm:
    print(f"Erro: não é possível ler {filename}. Você não tem permissão.")
  except ZeroDivisionError as err_de_div_por_zero:
    print(f"Erro: {filename} contém um zero na coluna de galões.")
def milhas_por_galao(milhas_iniciais, milhas_finais, galoes):
  """Calcula e retorna o número médio de milhas
  que um veículo percorreu por galão de combustível.
  Parâmetros
  milhas_iniciais: iniciando a leitura do odômetro em milhas.
  milhas_finais: finalizando a leitura do odômetro em milhas.
  galoes: quantidade de combustível consumido em galões americanos.
  Retorno: milhas por galão
  """
  mpg = abs(milhas_finais - milhas_iniciais) / galoes
  return mpg
# Chama main para iniciar este programa.
if __name__ == "__main__":
  main()

Validando a Entrada do Usuário

Validar a entrada do usuário significa verificar o que o usuário insere para garantir que esteja no formato correto antes de prosseguir com o uso. O programa no exemplo 12 valida a entrada do usuário ao processar exceções. Observe que a função obter_flutuante contém um bloco try na linha 23. O bloco try faz parte de um loop que valida a entrada do usuário na função obter_flutuante. Na linha 37, observe que o bloco except processa ValueError, que é o tipo de exceção que a função float gera quando tenta converter texto em número, mas o texto contém caracteres que não são numéricos.

# Exemplo 12
def main():
  genero = input("Digite seu gênero (M ou F): ")
  peso = obter_flutuante("Digite seu peso em kg: ", 20, 500)
  altura = obter_flutuante("Digite sua altura em cm: ", 60, 250)
  idade = obter_flutuante("Digite sua idade em anos: ", 10, 120)
  tmb = taxa_metabolica_basal (genero, peso, altura, idade)
  print(f"Sua taxa metabólica basal é de {tmb} calorias por dia.")
def obter_flutuante(prompt, limite_inferior, limite_superior):
  """Obtém um número do usuário, valida se o usuário
  digitou um número, e não outro tipo de texto, valida se
  o número está entre um limite inferior e superior e então
  retorna o número. Se o usuário digitar um número inválido,
  esta função solicitará um número válido
  até que o usuário o insira.
  Parâmetros
  prompt: Uma string para exibir ao usuário.
  limite_inferior: O menor número que o usuário pode inserir.
  limite_superior: O maior número que o usuário pode inserir.
  Retorno: O número inserido pelo usuário.
  """
  while True:
    try:
      texto = input(prompt)
      numero = float(texto)
      if numero < limite_inferior:
        print(f"{numero} é muito pequeno.")
        print("Por favor, digite outro número.")
      elif numero > limite_superior:
        print(f"{numero} é muito grande.")
        print("Por favor, digite outro número.")
      else:
        # Se o computador chegar a esta linha de código,
        # o usuário inseriu um número válido entre
        # limite_inferior e limite_superior, então sai do loop.
        break
    except ValueError as err_de_valor:
      # O usuário inseriu pelo menos um caractere que
      # não faz parte de um número de ponto flutuante, então exibe uma
      # mensagem solicitando que o usuário insira um número.
      print(f"{texto} não é um número.")
      print("Por favor, digite um número.")
  return numero
def taxa_metabolica_basal(genero, peso, altura, idade):
  """Calcula e retorna a taxa metabólica basal de uma pessoa
  em calorias por dia. O peso deve ser em quilogramas, a altura
  deve estar em centímetros e a idade deve estar em anos.
  """
  if genero.upper() == "F":
    tmb = 447.593 + 9.247 * peso \ + 3.098 * altura - 4.330 * idade
  else:
    tmb = 88.362 + 13.397 * peso \   + 4.799 * altura - 5.677 * idade
  return tmb
# Chama main para iniciar este programa.
if __name__ == "__main__":
  main()

Documentação

Se os conceitos acima parecem vagos, estes tutoriais podem esclarecer algumas dúvidas que você possa ter:

A referência oficial das exceções embutidas do Python contém uma lista de todas as exceções embutidas. Ela também inclui a hierarquia de classes das exceções embutidas, que é útil para ordenar os blocos except do mais específico para o mais geral.

Resumo

Às vezes, ocorrem erros e situações excepcionais enquanto um programa está em execução. Quando uma situação excepcional acontece, o computador gera uma exceção. Com as palavras-chave try e except, você pode escrever código Python que processará exceções. Escreva o código do programa normal dentro de um bloco try e escreva um bloco except para cada tipo de exceção que você deseja que seu programa processe.

Existem vários tipos de exceções em Python, mas seu código precisará manipular apenas sete deles no CSE 111, a saber:

Ao escrever código que grava ou lê de um arquivo, um programador geralmente escreve blocos except para processar os erros FileNotFoundError e PermissionError. Além disso, ao escrever código que recebe entrada de um usuário, os programadores geralmente escrevem blocos try e except para ajudar a validar a entrada do usuário.

Atividade

Finalidade

Melhore sua compreensão de como lidar com exceções em um programa Python.

Tarefa

Faça o seguinte:

  1. Baixe e salve os arquivos acidentes.csv e obter_linha.py na mesma pasta. O programa obter_linha.py é simples, apenas pede ao usuário para inserir o nome de um arquivo de texto e o número da linha. Em seguida, ele exibe o texto da linha solicitada no arquivo .
  2. Abra obter_linha.py no VS Code e observe o bloco try na linha 10 e os cinco blocos except nas linhas 27–74, cada um tratando um tipo diferente de exceção.
  3. Execute o programa obter_linha.py cinco vezes e insira a entrada mostrada abaixo. Para cada uma das quatro primeiras vezes que você executar o programa, encontre as linhas de código em obter_linha.py que trataram a exceção gerada.

Exemplo de Execução

> python obter_linha.py
Digite o nome do arquivo de texto: naoeumarquivo.csv

FileNotFoundError: [Errno 2] No such file or directory: naoeumarquivo.csv
O arquivo naoeumarquivo.csv não existe.
Execute o programa novamente e digite o nome de um arquivo existente.

> python obter_linha.py
Digite o nome do arquivo de texto: acidentes.csv
Digite um número de linha: ei
ValueError: invalid literal for int() with base 10: 'ei'     
Você inseriu um número inteiro inválido para o número da linha.
Execute o programa novamente e insira um número inteiro para o número da linha.

> python obter_linha.py
Digite o nome do arquivo de texto: acidentes.csv
Digite um número de linha: -300
IndexError: list index out of range
-300 é um número inteiro negativo.
Execute o programa novamente e insira um número de linha entre 1 e 9.

> python obter_linha.py
Digite o nome do arquivo de texto: acidentes.csv
Digite um número de linha: 75
IndexError: list index out of range
75 é maior que o número de linhas em acidentes.csv.
Há apenas 7 linhas em acidentes.csv.
Execute o programa novamente e insira um número de linha entre 1 e 9 .

> python obter_linha.py
Digite o nome do arquivo de texto: acidentes.csv
Digite um número de linha: 4

2012,33782,2362000,5615000,31006,3167,440,9420,6396,1262

Envio

Quando terminar, reporte seu progresso no questionário do Canvas correspondente a esta atvidade.

Links Úteis: