Trabalhando com arquivos e diretórios no python

Trabalhando com arquivos e diretórios no python

No meu sistema de cadastro de produtos, preciso criar uma funcionalidade que, a partir de um arquivo CSV com dados dos produtos, eu consigo ler esse arquivo e separar todos os produtos contido nele. Para representar um produto temos a seguinte classe:


class Produto(object): 
  def __init__(self, nome, valor): 
    self.__nome = nome 
    self.__valor = valor

  @property 
  def nome(self): 
    return self.__nome

  @nome.setter 
  def nome(self, nome): 
    self.__nome = nome

  @property def valor(self): 
    return self.__valor

  @valor.setter 
  def valor(self, valor): 
    self.__valor = valor 

  def __repr__(self): 
    return "nome:%s valor:%s" % (self.__nome, self.__valor)

Inicialmente temos o arquivo dados.csv com o seguinte conteúdo:

 nome, valor camiseta, 25.0 jaqueta, 125.0 tenis, 80.0 bermuda, 40.0

Nesse meu sistema, irei ler esse arquivo a partir do diretório "arquivos/produtos/" portanto, criaremos a variável arquivo indicando o caminho e o nome do arquivo que leremos:


arquivo = 'arquivo/produtos/dados.csv'

Implementando a função de leitura do arquivo

Agora precisamos criar uma função que ficará responsável em ler esses produtos por meio da variável arquivo, portanto, criaremos a função ler_produtos() passando o arquivo como parâmetro:


def ler_produtos(arquivo):

arquivo = 'arquivo/produtos/dados.csv'

Primeiro, precisamos abrir o arquivo CSV, ou seja, utilizaremos a função open enviando a variável arquivo e utilizando parâmetro 'rb' que indica leitura:


def ler_produtos(arquivo):
   arquivo_aberto = open(arquivo, 'rb')

No Python, para ler um arquivo CSV, podemos utilizar a função reader do módulo csv, porém, precisamos importar o módulo:


import csv

def ler_produtos(arquivo): 
  arquivo_aberto = open(arquivo, 'rb') 
  return csv.reader(arquivo_aberto,delimiter=',')

Observe que também adicionamos o parâmetro delimiter que já separa cada informação a partir de um critério, nesse caso, cada informação será separada no momento em que aparecer uma vírgula, e também, estamos retornando a função reader que é justamente o arquivo lido.

Então vamos realizar um teste, faremos a chamada para a função ler_produtos e devolveremos para a variável dados:


import csv

def ler_produtos(arquivo): 
  arquivo_aberto = open(arquivo, 'rb') 
  return csv.reader(arquivo_aberto,delimiter=',')

arquivo = 'arquivo/produtos/dados.csv'

dados = ler_produtos(arquivo)

Rodando o nosso código temos o seguinte resultado:

 IOError: [Errno 2] No such file or directory: 'arquivo/produtos/dados.csv'
Banner da Escola de Programação: Matricula-se na escola de Programação. Junte-se a uma comunidade de mais de 500 mil estudantes. Na Alura você tem acesso a todos os cursos em uma única assinatura; tem novos lançamentos a cada semana; desafios práticos. Clique e saiba mais!

Verificando a existência do arquivo

Opa! Ele não conseguiu achar o meu arquivo! Por que será que isso aconteceu? Vejamos dentro do diretório onde está o meu projeto:

 > ls dados.csv model.py verificando_diretorio.py

De fato não existe esse diretório, então o que devemos fazer? Antes mesmo de tentarmos pegar o arquivo, temos que verificar se ele pelo menos existe! Em outras palavras, precisamos primeiro verificar se o caminho que queremos encontrar existe, caso não exista, precisamos criá-lo!

Portanto, o nosso primeiro passo é separar a variável arquivo em duas, ou seja, a arquivo e caminho:


caminho = 'arquivo/produtos' 
arquivo = caminho + '/dados.csv'

Em seguida, vamos criar a função verificar_arquivo, que será responsável em verificar se o diretório existe e o arquivo também, caso não exista, ela deverá criá-los! Então vamos criá-la:


import csv

def verificar_arquivo(): 
  caminho = 'arquivo/produtos' arquivo = caminho + '/dados.csv'

def ler_produtos(arquivo): 
  arquivo_aberto = open(arquivo, 'rb')
  return csv.reader(arquivo_aberto,delimiter=',')

dados = ler_produtos(arquivo)

Verificando a existência do diretório

Qual é o nosso próximo passo? É justamente verificar se o diretório não existe. Para isso, no Python, podemos utilizar o módulo os com funções capazes de realizar chamadas de sistema.

Nesse nosso primeiro caso, utilizaremos a função path.exists que verifica se existe um arquivo ou diretório com o parâmetro informado:


import csv import os

def verificar_arquivo(): 
  caminho = 'arquivo/produtos' 
  arquivo = caminho + '/dados.csv'

if not os.path.exists(caminho):

Observe que estamos varificando se o diretório não existe, caso isso for verdade, o que devemos fazer? Precisamos criar o diretório! Mas como criamos um diretório no Python? Simples! No modulo os, temos também a função makedirs que cria diretórios:


def verificar_arquivo(): 
  caminho = 'arquivo/produtos' 
  arquivo = caminho + '/dados.csv'

if not os.path.exists(caminho):
   os.makedirs(caminho)

O nosso próximo passo é verificar a existência do arquivo dentro desse diretório. Podemos utilizar novamente a função path.exists do módulo os. Da mesma forma como fizemos com o diretório, caso não exista o arquivo, precisamos criá-lo.

Criando o arquivo

Para criar um arquivo, utilizaremos a função open passando o segundo parâmetro com o valor "w" que indica a criação para escrita:


def verificar_arquivo(): 
  caminho = 'arquivo/produtos' 
  arquivo = caminho + '/dados.csv'

if not os.path.exists(caminho): 
  os.makedirs(caminho)
if not os.path.exists(arquivo): 
  open(arquivo, 'w')

Por fim, retornamos a variável arquivo para lermos na função ler_produtos:


def verificar_arquivo(): 
  caminho = 'arquivo/produtos' 
  arquivo = caminho + '/dados.csv'

  if not os.path.exists(caminho): 
    os.makedirs(caminho)

  if not os.path.exists(arquivo): 
    open(arquivo, 'w')

  return arquivo

Agora, basta apenas chamarmos a função verificar_arquivo devolvendo o seu resultado para a variável arquivo, e então, chamamos a função ler_produtos enviando a variável arquivo como parâmetro:


arquivo = verificar_arquivo() dados = ler_produtos(arquivo)

Exibindo as informações

Agora vamos imprimir os dados para verificar os valores, porém, ao invés de fazer um for de forma procedural, utilizaremos o recurso de compreensão de lista:


print [dado for dado in dados]

Executando o código temos o seguinte resultado:

 [['nome', ' valor'],
 ['camiseta', ' 25.0'],
 ['jaqueta', ' 125.0'], 
 ['tenis', ' 80.0'],
 ['bermuda', ' 40.0']]

Note que o primeiro valor ainda é o cabeçalho, isto é, linhas 'nome' e 'valor'. Para eliminarmos esse cabeçalho basta chamarmos a função next antes de iterar a variável dados:


next(dados) print [dado for dado in dados]

Por fim, basta apenas armazenarmos os valores em objetos do tipo Produto:


produtos = [Produto(dado[0], dado[1]) for dado in dados] print produtos

Rodando o código novamente, temos o seguinte resultado:

[nome:camiseta valor: 25.0,
nome:jaqueta valor: 125.0,
nome:tenis valor: 80.0,
nome:bermuda valor: 40.0]

Situações inesperadas

Observe que todos os dados foram lidos sem nenhum problema! Entretanto, se o caminho "arquivo/produtos" ao invés de ser um diretório, fosse um arquivo? O que será que aconteceria com o nosso código?

Vamos fazer uma simulação! Primeiro eu vou alterar o nome do diretório para "arquivo/produtos" para "arquivo/produtos1" e então, vou criar um arquivo chamado "produtos" dentro do diretório "arquivo":

arquivo_sem_extensao

Testando o nosso código, temos o seguinte resultado:

 Traceback (most recent call last): File "/home/alex-felipe/python/dir.py", line 22, in <module> arquivo = verificar_arquivo() 

 File "/home/alex-felipe/python/dir.py", line 14, in verificar_arquivo open(arquivo, 'w') IOError: \[Errno 20\] Not a directory: 'arquivo/produtos/dados.csv'

Veja que ele tentou abrir o arquivo com a função open porém percebeu que o "arquivo/produtos" trata-se de um arquivo! Em outras palavras, permitimos que o nosso algoritmo seguisse adiante... Então o que devemos fazer?

Antes mesmo do nosso algoritmo tentar abrir o arquivo, precisamos garantir que o caminho é válido! Portanto, logo no momento que verificamos se não existe o caminho:


if not os.path.exists(caminho): os.makedirs(caminho)

Podemos adicionar uma elfi que será acionado caso exista um arquivo ou diretório de acordo com o caminho especificado, e então, vai verificar se o caminho não é um diretório:


if not os.path.exists(caminho): os.makedirs(caminho) elif not os.path.isdir(caminho):

Caso for verdade, ou seja, o caminho especificado não for um diretório, simplesmente lançamos um erro de IOError avisando que o caminho que estamos utilizando não é um diretório:


if not os.path.exists(caminho): os.makedirs(caminho) elif not os.path.isdir(caminho): raise IOError(caminho + " nao eh um diretorio!")

Agora, quando existir um arquivo ou diretório no caminho especificado e não for um diretório, automaticamente paramos o nosso algoritmo! Vejamos o resultado no teste:

 Traceback (most recent call last): File "/home/alex-felipe/python/dir.py", line 22, in <module> arquivo = verificar_arquivo() File "/home/alex-felipe/python/dir.py", line 11, in verificar_arquivo raise IOError(caminho + " nao eh um diretorio!") IOError: arquivo/produtos nao eh um diretorio!

Veja que agora, mesmo em casos exceptionais como este, o nosso algoritmo consegue lidar e tomar as decisões necessárias.

Conclusão

Nesse post, vimos os problemas que podemos ter durante a leitura de arquivos dentro de diretórios, isto é, antes de tentarmos realizar a leitura de um arquivo precisamos sempre verificar se o caminho, nesse caso diretório, e o arquivo realmente existem, caso não, precisamos criá-los, caso sim, apenas lemos!

Gostou da dica? Então compartilhe conosco o que achou nos comentários :)

E que tal aprender a desenvolver com o Python hoje mesmo? Na Alura, temos a cursos de Python, onde você vai aprender desde o zero até uma aplicação web usando o Python.

Alex Felipe
Alex Felipe

Alex é instrutor e desenvolvedor e possui experiência em Java, Kotlin, Android. Atualmente cria conteúdo no canal https://www.youtube.com/@AlexFelipeDev.

Veja outros artigos sobre Programação