Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

Trabalhando com arquivos e diretórios no python

Boa noite,

Eu tenho as funções abaixo, porém eu não consigo ler o arquivo, ele retorna o seguinte erro:

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)
import csv
import os


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


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


arquivo = verificar_arquivo()

dados = ler_produtos(arquivo)

print([dado for dado in dados])
9 respostas

Faaala Rafael, tudo bem com você?

O motivo desse erro é por causa que está lendo o arquivo como rb. O formato rb é para leitura de arquivos binários. Se esse não for o seu caso, você pode utilizar apenas o r ao invés de rb.

Qualquer dúvida estou a disposição. Abraços e bons estudos!

Oi Nádia, boa tarde.

Eu não estou conseguindo obter o resultado abaixo, com o código informado acima.

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

A minha saída fica da seguinte maneira:

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

Aonde eu chamo a função NEXT(), para eliminar o cabeçalho ['nome', ' valor'] ?

Rafael, você terá que alterar a função ler_produtos. Atualmente você faz o retorno do cvs.reader diretamente, certo? Como essa função irá retornar um iterável, para você utilizar o next e ignorar o cabeçalho(primeira linha), você terá que atribuir cvs.reader a uma variável e chamar o next para essa variável e após isso, fazer o retorno. Muito teórico? Vamos ver como fica isso em código:

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

Com isso, creio que você obterá o resultado esperado. Caso ainda não consiga o que você espera, vamos conversando que irei te ajudar.

Oi Nádia, boa noite.

Agora estou com o código refeito, conforme orientação, porém ele me retorna uma lista vazia.

import csv
import os


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

    if not os.path.exists(caminho):
        os.makedirs(caminho)
    elif not os.path.isdir(caminho):
        raise IOError(caminho + ' não é um diretório !')

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

    return arquivo


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


arquivo = verificar_arquivo()

dados = ler_produtos(arquivo)

print([dado for dado in dados])

Oii Rafael, boa noite. Suponho que seu arquivo csv tenha a seguinte estrutura:

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

Quando executo seu código obtenho a saída esperada. Veja neste link (Clique em run no main.py)

Um detalhe em relação a seu código: se não existir aquele caminho e o programa criar, o arquivo dados.csv será vazio, logo, não terá dado algum. Como está organizado seu arquivo dados.csv?

Oi Nádia, boa tarde.

Segue a estrutura do arquivo:

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

Rafael, boa tarde. Eu partia do pressuposto que seu arquivo estava organizado da seguinte maneira:

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

E estando ele dessa forma, o código anterior obteria o resultado desejado. Uma vez que o next faria com que a primeira linha(nome, valor) fosse ignorada.

Porém, como o seu arquivo está organizado da seguinte forma:

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

Teremos que partir para outra abordagem. Não será necessário utilizar o next.

A primeira mudança que será feita, é em relação ao delimitador do retorno do arquivo, que agora será um espaço.

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

Dessa forma, iremos obter separadamente cada palavra daquela linha. Exemplo:

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

Agora, podemos percorrer essa lista e ignorar o primeiro e o segundo elemento que são: nome,(posicao 0 da lista) e valor(posicao 1 da lista).

E observe que no resultado acima, possuímos algumas vírgulas indesejadas, como por exemplo em: 'camiseta,'. Para lidar com isso, podemos utilizar o método replace, substituindo a vírgula por um "nada".

Em código fica da seguinte forma:

item_valor = 0

for dado in dados:
    qtd_de_itens_na_linha = len(dado)
    for item in range(qtd_de_itens_na_linha):
        if item > 1: 
            if item_valor == 0:
                print(dado[item].replace(',',''), end=" ")
                item_valor += 1
            elif item_valor == 1:
                print(dado[item].replace(',',''), end="\n")
                item_valor = 0

A variável item_valor serve apenas como controle para que possamos printar nome do produto e o preço em uma mesma linha. A ideia é: printou o nome do produto, então dê um espaço(end=" ") e no próximo item printe o valor e dê uma quebra de linha(end="\n").

Resultado:

camiseta 25.0
jaqueta 125.0
tenis 80.0
bermuda 40.0

Código completo:

import csv
import os


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

    if not os.path.exists(caminho):
        os.makedirs(caminho)
    elif not os.path.isdir(caminho):
        raise IOError(caminho + ' não é um diretório !')

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

    return arquivo


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


arquivo = verificar_arquivo()

dados = ler_produtos(arquivo)

item_valor = 0

for dado in dados:
    qtd_de_itens_na_linha = len(dado)
    for item in range(qtd_de_itens_na_linha):
        if item > 1: 
            if item_valor == 0:
                print(dado[item].replace(',',''), end=" ")
                item_valor += 1
            elif item_valor == 1:
                print(dado[item].replace(',',''), end="\n")
                item_valor = 0

Vale ressaltar que tivemos que partir para uma abordagem mais verbosa devido a forma como os dados no seu arquivo csv estão organizados. Caso eles estivessem organizados em coluna(da forma como eu imaginei) , a primeira abordagem seria suficiente.

Outro detalhe é em relação a caso não exista o caminho, pois como será feito a criação o arquivo dados.csv estará vazio e isso pode levar seu código a ter erros silenciosos. O que eu o recomendo fazer é caso não exista o caminho, lance uma exceção falando que aquele caminho não existe. Forçando que a pessoa o crie e alimente a planilha de dados.csv. Tudo bem?!

solução!

Rafael, peço por gentileza se caso a resposta tenha sanado sua dúvida, marque-a como solução para que esse tópico possa sair da lista de questões sem solução do fórum e ajude outros alunos que possuírem a mesma dúvida.

Caso tenha dúvidas, é só falar. Me coloco à disposição. Abraços e bons estudos!

Oi Nádia, bom dia.

Foi mal, esqueci de marcar como solucionada.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software