Форум сайта python.su
0
Всем привет. :) Извиняюсь за длинное изложение, но очень важно передать суть проблемы.
<Лев Толстой mode on>
Мне была поставлена задача, написать приложение, которое вычисляет некоторый хэш с помощью некоторой функции от 100к соли и делает распределение полученного результата (т.е. полученные 100к хэшей) по заданному файлу (те делается конкатенация строки из файла и хэша строка::хэш). Приложение должно эффективно использовать системные ресурсы.
Я написал следующий код (во вложении) и в результате получил примерно следующий комментарий “в решении есть логические недочеты и на большой платформе это выйдет боком, тебе необходимо менять мышление.”
Буду рад любой критике и замечаниям. У меня есть огромное желание научиться писать качественный код, которой бы работал эффективно и его было бы легко поддерживать.
Приму любую помощь тут или по скайпу “bel.mih”.
</Лев Толстой mode off>
Отредактировано zloymih (Фев. 17, 2016 20:28:36)
Прикреплённый файлы:
masterfoo.py (3,9 KБ)
Офлайн
857
1)
Вот у тебя везде там sys.exit() по коду разбросаны. Представь, что этот код импортируется в другой код и становится там лишь мелкой частью какой-то. Зачем эти sys.exit()'ы? Или ты думаешь “я потом переделаю”? Не переделаешь, потом надо будет делать другие дела. В главном потоке должен обрабатываться выход, чтобы можно было по-другому реагировать, если поток не сработал.
2)
Там, когда файл читаешь, весь его загоняешь в память. (Ну, это легко исправить.)
Используй генераторы.
zloymihЧто это вообще за хрень? Во втором питоне map() и так возвращает список.lines = list(s for s in map(string.strip, my_file))
zloymihСпроектируй сначала это всё, опиши, что должен делать каждый поток и зачем он нужен.
написать приложение, которое вычисляет некоторый хэш с помощью некоторой функции от 100к соли и делает распределение полученного результата (т.е. полученные 100к хэшей) по заданному файлу (те делается конкатенация строки из файла и хэша строка::хэш).
Офлайн
0
Большое спасибо за хороший анализ.
Появились еще вопросы:
А то, что я все оформил в виде одного класса это правильно? Пишут так или нужно разбивать на отдельные классы?
Могут ли возникать проблемы, когда методы одного класса вызываются в разных процессах.
Как правильно (общеприянто) обрабатывать ошибки в подпроцессе и корректно его завершать?
Легко ли поддерживать такой код, как у меня?
Офлайн
857
zloymihКласс нужно делать, когда у тебя есть одни данные, с которыми работают несколько функций.
А то, что я все оформил в виде одного класса это правильно?
zloymihЕсли делаешь новый класс, должен задаваться вопросом “что будет делать этот класс, для чего он?”. Вот потренируйся на списке list, как будто его нет и ты должен его сделать.
Пишут так или нужно разбивать на отдельные классы?
zloymihМетоды могут быть чистыми, а могут быть с побочными эффектами. Но даже чистые методы могут работать с одними данными, одновременный доступ к которым может приводить к ошибкам. Это тонкая тема, нужно хорошо понимать, что делают процессы и чего не делают.
Могут ли возникать проблемы, когда методы одного класса вызываются в разных процессах.
zloymihГлавный поток должен получать сообщение об ошибке от дочернего и принимать решение о его завершении, посылая сигнал. Короче, должна быть возможность послать и остальным потокам сигнал, что в этом одном произошла ошибка.
Как правильно (общеприянто) обрабатывать ошибки в подпроцессе и корректно его завершать?
zloymihТы сам откроешь его через год или два и поймёшь. Поймёшь, что написана бурда, которую можно только заново переписать. А времени на это не будет. Вот так же он выглядит для незнакомого человека.
Легко ли поддерживать такой код, как у меня?
Отредактировано py.user.next (Фев. 18, 2016 12:54:02)
Офлайн
0
Благодарю за столь подробный ответ. Постараюсь переписать код с учетом вышесказанного.
Офлайн
0
В процессе написания возникли затруднения в синхронизации потоков и способами обмена информацией между ними.
Предполагаю, что для решения первой проблемы нужно использовать threading.Event().
А для решения второй проблемы ничего кроме Queue() не придумал. Есть сомнения насчет передачи одной строки из файла через очередь. Мне кажется это накладно. Загружать все строки в очередь - еще хуже. Как правильно в таком случае: использовать глобальную переменную или другой способ? Мой код с учетом замечаний во вложении.
Буду рад замечаниям и критике. Стало лучше или вообще лапша получилась?
Прикреплённый файлы:
masterfoo_v4.py (4,5 KБ)
Офлайн
857
Вот теперь в этом коде замени входной и выходной файлы, на входной и выходной сокеты. Для этого надо опять всё переписывать, потому что ты не открытые файлы передал потокам, а имена файлов, которые потоки открывают. И теперь, чтобы это заменить на сокеты-шмокеты, тебе нужно вникать в каждый поток и редактировать его. А когда файлы нужно будет вставить обратно, надо будет держать копию кода.
zloymihКогда делаешь потоки, нужно представлять, что запускаешь их в порядке 1 2 3 4 5, а работать они будут в порядке 5 4 3 2 1. Блокировками управляют очереди. Если в очереди есть элемент, то он может читаться. Если в очереди нет элемента, то он ожидается. Если все элементы переданы, то очередь закрывается.
В процессе написания возникли затруднения в синхронизации потоков
zloymihТы сначала напиши, чтобы это хотя бы работало, а оптимизировать будешь потом. Иначе получается, что программы у тебя нет, зато есть куча оптимизированных кусков, которые можно только выкинуть.
использовать глобальную переменную или другой способ?
zloymihЛапша стала лучше. Приличнее всего выглядит функция main(). Но в ней должны открываться файлы.
Стало лучше или вообще лапша получилась?
Офлайн
0
py.user.nextЯ учусь. Если бы я умел, то вопросов бы не задавал, а помогал бы другим, как вы. То, что для вас кажется очевидным, для меня кажется запутанным. Спасибо вам за помощь.
Ты должен один раз написать и забыть. А ты по 500 раз переписываешь.
py.user.nextСделал все через очереди. Программа работает. Но получился монстр. Поддерживать такое сложно. Можно код улучшить?
Ты сначала напиши, чтобы это хотя бы работало, а оптимизировать будешь потом.
Прикреплённый файлы:
masterfoo_v5.py (5,7 KБ)
Офлайн
857
zloymihТам много лишнего. Если в очередь больше нечего добавлять, закрывай её. А те, кто её прослушивает, по этому закрытию должны делать вывод, что надо завершать работу.
Сделал все через очереди. Программа работает.
Отредактировано py.user.next (Фев. 21, 2016 06:36:01)
Офлайн