Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 10, 2017 12:14:28

whoami217
Зарегистрирован: 2017-09-09
Сообщения: 22
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

py.user.next, записала, таким образом:

 rdn = csv.reader(fhand, delimiter=';')
for i in rdn:
    print(', '.join(i))

Вывело ошибку:
Enter a file name: text.csv
avr, atv, bmv
6246.09375, 55856.25, 38.625
6230.859375, 55856.25, 38.625
6230.859375, 55856.25, 38.625
6213.28125, 55856.25, 38.625
6213.28125, 55856.25, 38.625
6195.703125, 55856.25, 38.625
6195.703125, 55856.25, 38.625
6179.296875, 55912.5, 42
6179.296875, 55912.5, 42
6162.890625, 55912.5, 42
6162.890625, 55912.5, 42
6146.484375, 55912.5, 42
6146.484375, 55912.5, 42
6128.90625, 55912.5, 42
6128.90625, 55912.5, 42
6111.328125, 55987.5, 45.625
6111.328125, 55987.5, 45.625
6094.921875, 55987.5, 45.625
6094.921875, 55987.5, 45.625
6077.34375, 55987.5, 45.625
6077.34375, 55987.5, 45.625
6060.9375, 55987.5, 45.625
6060.9375, 55987.5, 45.625
6043.359375, 56062.5, 49.25
6043.359375, 56062.5, 49.25
6026.953125, 56062.5, 49.25
6026.953125, 56062.5, 49.25
6010.546875, 56062.5, 49.25
6010.546875, 56062.5, 49.25
———————————————————
If you want to EXIT this program then type - done
Enter the required parameter: bmv
Traceback (most recent call last):
if not (param in title):
NameError: name ‘title’ is not defined
Добавила строчки кода, чтобы ещё раз перематывать через fhand.seek(0):
 import csv
import string
 
fname = input("Enter a file name: ")
outputfile = "out.csv"
try:
    fhand = open(fname, mode='r', newline='')
    fcopy = open(outputfile, mode='w')
except:
    print ("File don’t exist: ", fname)
    exit()
rdn = csv.reader(fhand, delimiter=';')
for i in rdn:
    print(', '.join(i))
fhand.seek(0)
rdn = csv.reader(fhand, delimiter=';')
for title in list(rdn)[:1]:
    print("This file has parameters: ")
    print(title)
    
'''
rdn = csv.reader(fhand, delimiter=';')
i = ' '.join(list(rdn)[0])
print(i)
'''
while True:
    print("---------------------------------------------------------")
    print("If you want to EXIT this program then type - done")
    param = input("Enter the required parameter: ") 
    
    if param == "done":
        break
    if not (param in title):
        print("This parameter doesn't exist. Please try again")
        exit()
    rdn = csv.reader(fhand, delimiter=';')
    print("This file has parameters: ")
    print(title)
    titleIndex = title.index(param)
    print(titleIndex)
    fhand.seek(0)
    wrtr = csv.writer(fcopy, dialect='excel')
    for row in rdn:
        wrtr.writerow(row)
    print("---------------------------------------------------------")
fhand.close()
fcopy.close()

Но записывает в out.csv также как и в первый раз при введении только одного параметра:
avr,atv,bmv

6246.09375,55856.25,38.625
и т.д.

Отредактировано whoami217 (Сен. 10, 2017 12:15:17)

Офлайн

#2 Сен. 10, 2017 12:34:11

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

Да, дело серьёзное. Придётся, видимо, твой код всё-таки прочитать…
Короче, неправильно у тебя всё в плане логики, надо всё по новой делать.

Во-первых, с какого перепугу оно там выходит вообще из программы, если параметр введён неверный? Во-вторых, с чего ты взяла, что exit() - это правильный способ выхода из программы? exit() применяется только в интерпретаторе, когда сидишь в нём руками. Для выхода из программы применяется функция sys.exit() - совсем другая функция. И то выход посреди программы не рекомендуется использовать, потому что программа может стать частью большей программы, которая не должна будет выходить где-то там внутри своего кода. Там нужно поставить continue, чтобы цикл заново пошёл (перешёл на следующий шаг).

whoami217
1. спрашивали название файла, который нужно пропарсить,
2. добавляли новый файл csv, куда необходимые нам колонки вставлялись в файл,
3. спрашивали, какие параметры мы хотим получить в новом файле txt,
4. вводили параметры,
5. и записывали эти колонки с параметрами и их значениями в новый файл.
Может, тебе функции попробовать? Задание вполне прилично смотрится и напрашивается на функции.

Тебе нужно ввести все имена полей, а потом, когда они уже все введены, писать в файл вывода их, вибирая из файла ввода. А у тебя оно на ходу пытается что-то писать, что, естественно, неправильно. Писать надо один единственный раз все выбранные колонки.



Отредактировано py.user.next (Сен. 10, 2017 12:36:45)

Офлайн

#3 Сен. 10, 2017 13:14:30

whoami217
Зарегистрирован: 2017-09-09
Сообщения: 22
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

py.user.next, насчёт continue я поняла, обязательно применю. Насчёт функций. Функции для меня достаточно тяжёлые для понимания, так как не всегда понятно что нужно возвращать в return. Но я попытаюсь сделать через функции.

Тебе нужно ввести все имена полей, а потом, когда они уже все введены, писать в файл вывода их, выбирая из файла ввода.

Ввести все имена полей, которые мне нужно получить в out.csv? При этом указав количество этих полей? Или лучше что-то подобное: ‘1’ - продолжить ввод полей, ‘2’ - закончить ввод полей и приступить к следующему этапу? Запись в файл будет происходить через for?
 for row in rdn:
        wrtr.writerow(row)

Офлайн

#4 Сен. 10, 2017 13:27:57

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

whoami217
Функции для меня достаточно тяжёлые для понимания, так как не всегда понятно что нужно возвращать в return. Но я попытаюсь сделать через функции.
Вот код примерный, как должно это на функциях смотреться
#!/usr/bin/env python3

# создаёт матрицу
# заменяет в ней одно число на другое

import random

def input_values():
m = int(input('Enter m: '))
n = int(input('Enter n: '))
f = int(input('Enter f: '))
return m, n, f

def create_matrix(rows, cols):
matr = [[random.randint(-10, 10) for j in range(cols)]
for i in range(rows)]
return matr

def print_matrix(pref, matr):
print(pref, end='')
rows, cols = len(matr), len(matr[0])
for i in range(rows):
for j in range(cols):
print('{0:5}'.format(matr[i][j]), end='')
print()

def process_matrix(matr, num, to):
rows, cols = len(matr), len(matr[0])
i = 0
while i < rows:
j = 0
while j < cols:
if matr[i][j] != num:
matr[i][j] = to
j += 1
i += 1
return matr

def main():
m, n, f = input_values()
matr = create_matrix(m, n)
print_matrix('was:\n', matr)
process_matrix(matr, f, 0)
print_matrix('new:\n', matr)

if __name__ == '__main__':
main()

Ещё здесь был случай типа твоего. Только он сложнее, потому что там файлы Excel'я были и их нужно было преобразовать по очень запутанной схеме. И она тогда сделала, как у тебя, только там это было нереально сделать без функций, потому что всё очень запутано логически. Там можно посмотреть, как она без функций пыталась это сделать и как я перевёл это на функции. Оно не только понятнее становится, но и безошибочнее (контроль распределяется по функциям, которые сами по себе простые).

whoami217
Ввести все имена полей, которые мне нужно получить в out.csv? При этом указав количество этих полей?
Нужна функция получения названий полей. Потом, когда она получила и вернула названия, они передаются дальше в другую функцию. А она уже их берёт и использует для ввода нужных полей (проверка на наличие поля). Когда подходящие поля введены, они возвращаются из функции и дальше они передаются в другую функцию, которая уже из файла ввода выбирает только по ним и, в идеале, возвращает итератор по строкам, в которых только выбранные поля. А дальше этот итератор берётся и подаётся в следующую функцию, которая из него пишет в файл вывода. То есть каждая функция отвечает за своё дело какое-то небольшое. На матрице посмотришь: функция main() управляет функциями готовыми, передавая данные и результаты между ними, а каждая функция выполняет только свою мелкую, но конкретную задачу.


tags: matrix



Отредактировано py.user.next (Май 24, 2019 02:08:09)

Офлайн

#5 Сен. 10, 2017 14:06:29

vic57
Зарегистрирован: 2015-07-07
Сообщения: 899
Репутация: +  126  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

whoami217
Также можете предложить свой альтернативный код.
тут csv не особо и нужен ЕЯПП
 while True:
    f_in = input("Исходный файл? ")
    try:
        with open(f_in) as f:
            lines = f.readlines()
            break
    except Exception as e:
        print(str(e))
             
title = [ i.strip() for i in lines[0].split(';') if i.strip()]
#print(title)
flag = True
while flag:
    print('Колонки исходного файла: ',' '.join(title))
    val = input('Введите колонки для выходного файла(через пробел)  ')
    hdr = [i.strip() for i in val.split() if i.strip()]
    flag = False
    for i in hdr:
        if not i in title:
            print('Неверные данные:',i)
            flag = True
    
indexes = []
for i in hdr:
    indexes.append(title.index(i))
#print(hdr,indexes)
f_out = input("Выходной файл? ")
f = open(f_out,'w')
f.write(';'.join(hdr) + '\n')
for line in lines[1:]:
    l = [i.strip() for i in line.split(';') if i.strip()]
    tmp = []
    for i in indexes: tmp.append(l[i])
    f.write(';'.join(tmp) + '\n')
f.close()

Офлайн

#6 Сен. 10, 2017 14:20:26

whoami217
Зарегистрирован: 2017-09-09
Сообщения: 22
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

py.user.next, спасибо за пример работы с функциями.

Офлайн

#7 Сен. 10, 2017 14:25:54

whoami217
Зарегистрирован: 2017-09-09
Сообщения: 22
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

vic57, вы прекрасно меня поняли. Спасибо за предоставленный код. Проверила, что он рабочий. Теперь осталось разобрать весь код построчно, поскольку есть моменты, в которые сложно вникнуть сразу.

Офлайн

#8 Сен. 10, 2017 15:54:30

vic57
Зарегистрирован: 2015-07-07
Сообщения: 899
Репутация: +  126  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

whoami217, добавил комментарии

 while True:
    f_in = input("Исходный файл? ")
    try:
        with open(f_in) as f:
            lines = f.readlines()#читаем файл в list
            break
    except Exception as e:
        print(str(e))
             
title = [ i.strip() for i in lines[0].split(';') ]# заголовки входного файла(list)
#print(title)
flag = True
while flag:
    print('Колонки исходного файла: ',' '.join(title))
    val = input('Введите колонки для выходного файла(через пробел)  ')
    hdr = [i.strip() for i in val.split() ]  # заголовки выходного файла (list)
    flag = False
    for i in hdr:
        if not i in title:
            print('Неверные данные:',i)
            flag = True
    
indexes = []
for i in hdr:
    indexes.append(title.index(i))
#print(hdr,indexes)
f_out = input("Выходной файл? ")
f = open(f_out,'w')
f.write(';'.join(hdr) + '\n')
for line in lines[1:]: #данные
    l = [i.strip() for i in line.split(';') ]# разбиваем строку по delimiter в список, удаляем перевод строки
    tmp = []# пустой список
    for i in indexes: tmp.append(l[i]) # заносим значения по индексам в список
    f.write(';'.join(tmp) + '\n')# объединяем list в строку по delimiter, добавляем перевод строки
f.close()

Отредактировано vic57 (Сен. 10, 2017 16:11:36)

Офлайн

#9 Сен. 11, 2017 01:33:04

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Парсер файла csv на python3

whoami217, лучше на функциях делай. Конечно, хочется всё сделать быстро, но программирование - это не та область где нужно торопиться. Потеряешь просто в десять раз больше времени и, главное, не сделаешь ничего. Вот это программирование.

whoami217
Проверила, что он рабочий.
У тебя на входе csv-файл. Это что значит? Это значит, что у него прямо внутри поля может быть разделитель в проэкранированном виде. То есть это точка с запятой, но прямо внутри поля, в виде “123;456”. Поэтому csv никогда не разбирается как текст, потому что вот такие моменты бывают - когда разделитель может оказаться совсем не разделителем.

Второй момент. А откуда мы знаем, что у тебя в csv будут только числа всегда? Ниоткуда мы не знаем. У тебя программа должна по заданию просто фильтровать колонки. Нигде нет условия типа “в колонках всегда будут только числа” и “это гарантируется для всех будущих ситуаций”.

Поэтому мы и csv не разбираем как текст, и json не разбираем как текст. Эти модули знают, что там может быть внутри, и всё правильно парсят. Они не поведутся на разделитель внутри поля или кавычку где-то не там.

whoami217
в которые сложно вникнуть сразу
Конечно! Так там ещё и ошибки могут быть, которые не найдёшь при чтении из-за запутанности кода, но которые всплывут прямо при работе программы, когда уже не будет времени её менять. Сломается программа прямо посреди работы, для которой она предназначалась. Поэтому код должен быть читаемым (легко понимаемым), чтобы ошибки было видно сразу.

И ещё: функцию можно покрыть тестами (автоматические программки такие, которые проверяют множество значений на вход и выход), а монолитную программу тестами не покроешь (слишком дофига нужно тестов). Любую функцию можно выбрать и просто напрячь её тестами так, что она не сможет просто оказаться неправильной, потому что тесты будут залазить во все её слабые места и удостоверяться, что там всё правильно работает. Руками-то программы никто не проверяет, потому что после каждого изменения нужно снова проверять все-все-все случаи (а вдруг что-нибудь сломалось из-за новых изменений). Поэтому монолитки не пишут: они для тестов непригодны. Ты хочешь проверить, переходит ли программа на новый круг в цикле, если ввод неправильный, но ты не можешь это проверить, потому что у монолитной программы нет понятия “вот здесь ввод”. А когда у тебя функция ввода есть, то ты можешь просто начать её вызывать с разными вводами и проверять, перешла ли она на новый круг цикла при неправильном вводе и вышла ли она из цикла при правильном вводе. И так каждая функция проверяется отдельно со своим набором входных данных, нужных для полной проверки именно этой функции. Для ошибки не остаётся ни единого шанса где-то там запрятаться.

vic57
 f.write(';'.join(hdr) + '\n')
Вот ошибка. По RFC там должны быть CRLF везде, а тут только LF ставится. Заметил он ошибку? Нет, не заметил. А что типа, оно же выглядит похоже. А потом оно где-нибудь вылезет: в какой-нибудь винде в какой-нибудь программе напишет весь файл в одну строку. Да в простом блокноте даже виндовом открой csv-файл и вот этот файл - и увидишь квадратики в одной строке вместо нескольких строк.



Отредактировано py.user.next (Сен. 14, 2017 09:44:22)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version