Найти - Пользователи
Полная версия: Sberbank2Excel Программа для конвертации выписки Сбербанка по карте из формата PDF формат Excel
Начало » Python проекты » Sberbank2Excel Программа для конвертации выписки Сбербанка по карте из формата PDF формат Excel
1 2
Ev2geny
Друзья

сам я любитель и в качестве любительского проекта написал программу для конвертации выписки Сбербанка по карте из формата PDF формат Excel.

Т.к. выписка в формате PDF никак не поддаётся машинной обработке

На моей выписке программа работает, но требуется дополнительное тестирование.

Кому интересно - попробуйте протестировать https://github.com/Ev2geny/Sberbank2Excel

FishHook
Ev2geny
Вы ждёте конструктивную критику кода или она вам не нужна?
Ev2geny
FishHook
Ev2genyВы ждёте конструктивную критику кода или она вам не нужна?

Вообще-то я хотел попросить кого-нибудь, кому тоже интересна выписка из Сбербанка в формате Excel просто протестировать на собственных выписках (не может же быть что бы это нужно было бы только мне), но если Вы профессионал и готовы потратить на меня своё время, то конструктивная обратная связь по поводу кода будет конечно же приветствоваться.
FishHook
Ev2geny

Мне, признаться, совершенно плевать на выписки из сбербанка, а вот код мне интересен. Я не буду комментировать каждую вашу строку и докапываться до запятых, но несколько общих замечаний я сделать должен. Если вы в свою очередь тоже хотите стать профессионалом, вы прислушаетесь к моим рекомендациям.
Итак, что тут важно:
1) Ваш код нарушает один из главных принципов хорошего кода - принцип единичной ответственности. Ваша функция sberbankPDFtext2Excel делает всё и сразу. Это очень плохо по многим причинам. Такой код: трудно читать, трудно отлаживать и тестировать, трудно поддерживать.
Сравните два подхода:
 def doAll():
   ...
   # стопицот строк 
if __name__ == '__main__':
   doAll()

 if __name__ == '__main__':
    input_file_name = sys.argv[1]
    output_file_name = sys.argv[2]
    raw_data = read_data(file_name)
    parsed_data = parse_data(data)
    ...
    save_data(output_file_name)  

каждая ваша функция будет делать только что-то одно. В этом случае вы во-первых легко можете заменять одну реализацию на другую. Допустим, завтра сбербанк изменит формат своей выписки, вам придется вносить изменения только в тот компонент, который занимается парсингом файла, не зартрагивая другие компоненты. В общем-то вы можете иметь сразу два рабочих варианта одного и того же компонента, например, для разных версий API банка. Это сужает область возникновения ошибки и уменьшает когнитивную нагрузку на программиста, который будет поддерживать программу. Запомните, один компонент - одна ответственность.

2) Не игнорируйте принятые в отрасли стандарты. Есть документ PEP8 - который любой питонист должен знать наизусть. Он декларирует стиль программы, это на самом деле очень важно.

Кроме этого, конечно, есть и другие замечания, но это главно на что я хотел обратить ваше внимание.


Ev2geny
FishHook,
спасибо, что потратили время. Скажу честно, никогда ни один профессионал не комментировал мой код, польщён.

Но есть вопросы.

FishHook
Ваша функция sberbankPDFtext2Excel делает всё и сразу

1) У модуля sberbankPDFtext2Excel 2 фукцронала:

  • его можно запускать с командной строки, и тогда работает фукция main()
  • либо его можно импортировать и использовать функцию sberbankPDFtext2Excel()

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

2) Я уже использую модуль utils.py для разных функций, которые можно вынести

3) предложенный вами подход
  if __name__ == '__main__':
    input_file_name = sys.argv[1]
    output_file_name = sys.argv[2]
    raw_data = read_data(file_name)
    parsed_data = parse_data(data)
    ...
    save_data(output_file_name)  
предполагает, что одна функция получает на вход результаты работы другой. Но это не всегда возможно (либо разумно). Для вашего подхода нужна функциональность глобальных переменных, значит надо будет делать объект, а это муторно.

Или я что-то не догоняю?

FishHook
Есть документ PEP8 - который любой питонист должен знать наизусть. Он декларирует стиль программы, это на самом деле очень важно.

Обязательно почитаю. Но не могли бы вы крупными мазками описать что не так?




FishHook
Ev2geny
Таким образом мне нужна именно одна функция, которая выполняет весь функционал.
Нет. Сделайте вот так
 def run():
    input_file_name = sys.argv[1]
    output_file_name = sys.argv[2]
    raw_data = read_data(file_name)
    parsed_data = parse_data(data)
    ...
    save_data(output_file_name)  
У вас появится возможность импортировать запускалку, но у вас останется возможность:
1) тестировать каждый компонент как отдельную сущность (читать про юнит-тестирование)
2) локализовать баги согласно их принадлежности к функционалу конкретного компонента
3) держать код предельно ясным. Мне, человеку читающему вашу программу непонятно что именно делает на каждом шаге ваша суперфункция. Более того, есть такой закон https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%B3%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE_%D1%81%D0%B5%D0%BC%D1%8C_%D0%BF%D0%BB%D1%8E%D1%81-%D0%BC%D0%B8%D0%BD%D1%83%D1%81_%D0%B4%D0%B2%D0%B0, который ограничевает количество сущностей, которыми человек одновременно оперирует. Абстракции нужны, чтобы уменьшить количество объектов внимания.

я понимаю, что происходит
 parser = Parser()
data = parser.parse()
transformer = Transformer()
transformed_data = transformer(data)
saver = Saver()
saver.save_data(transformed_data ) 

я не понимаю что происходит
    
        result['operation_date']=line_parts[0]
        result['description']=line_parts[1]
        result['value_account_currency']=utils.get_float_from_money(line_parts[2],True)
        result['remainder_account_currency']=utils.get_float_from_money(line_parts[3])
        #************* looking at lines between 1st and the last
        sublines=lines[1:-1]
        for line in sublines:
            line_parts=utils.split_Sberbank_line(line)
            if len(line_parts)!=1:
                raise exceptions.SberbankPDFtext2ExcelError("Line is expected to have only one part :"+line)
            result['description']=result['description']+' '+line_parts[0]

я тупой, мне надо много времени, чтобы понять, в каком конкретно месте вашей программы происходит запись данных в эксель. Потому что я не вижу компонента, который за это отвечает. Поймите, что для того чтобы внести изменения в программу, надо понимать в каком месте это делается. Не продираться через горы каких-то циклов и непонятно чего, надо прочитать из каких модлулей состоит программа, найти класс Saver и его метод save. Изменения, которые я сделаю в этом методе не повлияют на все остальное. Я не знаю, что случится с вашей программой, если я изменю один байт в ней. Это может повлиять на чтение файла, на логику преобразования данных, на запись данных. Я знаю, что я поломаю, если я внесу изменения в метод save класса Saver.

Ev2geny
Для вашего подхода нужна функциональность глобальных переменных, значит надо будет делать объект, а это муторно.

Не понял. В каком месте вы увидели глобальные переменные. За глобальные переменные надо уши отрезать.

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

Ev2geny
FishHook,

спасибо за внимание.

Переписал, разбил всё на отдельные функции.

Посмотрите, так более читабельно? https://github.com/Ev2geny/Sberbank2Excel
mc-black
Здравствуйте! Мне как зеленому новичку интересно было посмотреть, что и как у Вас сделано. Мне интересно запускать программу из исходника, а не exe. В исходники бывает вкладывают файл зависимостей с указанием внешних библиотек или небольшую инструкцию по запуску проекта. Этого там я не нашел - буду пробовать с установкой pandas.

Скачал архив с бинарником и удивился - там куча библиотек и др., которые не используются в исходнике. В исходниках я видел только pandas и ст. библиотеку, а в “упаковку” вошел видимо весь набор библиотек, установленных глобально. Вероятно Вы не использовали virtualenv. Если так, рекомендую прочитать и проект оформлять в виртуальном окружении, исключительно с задействованными внешними библиотеками. Это сравнительно просто и применяется везде. В этом случае и exe-сборка у Вас должна получиться компактней и с тестированием у желающих трудностей не будет.

По поводу раздельного (вручную) распознавания foxit в текст. Это пожалуй слабое место, нельзя ли программно это сделать через интерфейс командной строки (если он есть) или через средства автоматизации? Может быть найдется бесплатная альтернатива, работающая из командной строки и без установки?

Про PEP8 тоже слышал, но руки не доходили его изучить - пожалуй возмусь. Вот его перевод.

По какому руководству/книге Вы изучали pandas?
mc-black
P.S. Пробовал установить на venv с Python 3.8 через pip, не вышло. Ищу причину, обновляюсь до Python 3.8.1 на всякий случай.
Ev2geny
mc-black
Скачал архив с бинарником и удивился - там куча библиотек и др., которые не используются в исходнике. В исходниках я видел только pandas и ст. библиотеку, а в “упаковку” вошел видимо весь набор библиотек, установленных глобально. Вероятно Вы не использовали virtualenv. Если так, рекомендую прочитать и проект оформлять в виртуальном окружении, исключительно с задействованными внешними библиотеками. Это сравнительно просто и применяется везде. В этом случае и exe-сборка у Вас должна получиться компактней и с тестированием у желающих трудностей не будет.
Не думаю, что virtualenv что-то изменит, по описанию pyinstaller подтягивает только те библиотеки, которые нужны. То что Вы думаете лишнее думаю используется в свою очередь pandas или tkinter. Но можно попробовать.

mc-black
Может быть найдется бесплатная альтернатива, работающая из командной строки и без установки?
Не нашёл ни нормальной библиотеки для питона ни бесплатной утилиты которая делала бы это с командной строки. Но может просто плохо искал

mc-black
Про PEP8 тоже слышал, но руки не доходили его изучить - пожалуй возмусь. Вот его перевод.
Спасибо, но советую читать на английском. Количество и качество информации на английском не сравнимо с русским (я не обязательно про PEP8. а вообще по питону).

mc-black
По какому руководству/книге Вы изучали pandas?
https://www.youtube.com/watch?v=ZyhVh-qRZPA
Потом просто google, на английском.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB