Найти - Пользователи
Полная версия: Покритикуйте прогу
Начало » Python для экспертов » Покритикуйте прогу
1 2
asv13
Написал программму статистики по логам игры Call of Duty.
На входе лог-файл, на выходе много .html с таблицами фрагов по игрокам и т.п.
Python 2.5, sqlite для базы, cheetah для шаблонов страниц, pyYAML для конфига, в котором прописаны настройки с SQL запросами по таблицам. Все это собрано PyInstaller-ом.
Не устраивает быстродействие, ранее была программа - только python без всех этих наворотов с конфигами и SQL, но захотелось гибкости и вот получаю тормоз.
исходники rar 40 Кб
Mkdir
1. Не пакуй в rar. Уважай linux-сообщество =) Распаковать rar можно, но лучше использовать более нейтральный формат - zip.
2. Используй в исходниках кодировку UTF-8.
3. Не пиши комментарии на русском. Имхо, это ламерство =) Т.е. я не имею в виду что ты ламер, но писать комментарии на русском как-то несерьёзно. Учитывай англоязыное сообщество. А оно в разы больше рускоязычного.
4. Между def ставь хотя бы один перенос строки ;)
5. “clock,key,tail = line”, “if key=='K':” после запятых, знаков равно и т.д. ставятся пробелы. У тебя сплошь и рядом тотальное отсутствие пробелов. Короче, по пункту 4 и 5 замечание общее: изучи стандарт кодирования (PEP-8) и свято ему придерживайся. Сбережёшь нервы себе и остальным =)
6.
try:
	cur.execute("SELECT max(id) FROM games")
	max_id = cur.fetchone()[0]
	print 'found max game num', max_id
	cur.execute("SELECT id, crashed, min_end, sec_end, pos FROM games WHERE id=%d" % max_id)
	row = cur.fetchone()
	print 'last game=',row
	if row[1]:
		print "last game has no ending line"
		sel = """
			DELETE FROM games WHERE id=%d;
			DELETE FROM actions WHERE game_number=%d;
			DELETE FROM hits WHERE game_number=%d;
			DELETE FROM players_time WHERE game_number=%d;
			DELETE FROM players_streak WHERE game_number=%d;
			""" % ((max_id,)*5)
		cur.executescript(sel)
		con.commit()
		sel = "SELECT id, crashed, min_end, sec_end, pos FROM games WHERE id IN (SELECT max(id) FROM games)"
		cur.execute(sel)
		row = cur.fetchone()
	pos = row[-1]
	n_games = row[0]
except:
	# в базе нет таблицы игр
	cur.executescript("""
	CREATE TABLE actions
		(id INTEGER PRIMARY KEY,
		game_number INTEGER,
		min INTEGER, sec INTEGER,
		idp INTEGER,
		side VARCHAR(10),
		player VARCHAR(70),
		action VARCHAR(20));
         ..........

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

Предлагаю:
а) вынести код, создающий таблицы, в отдельную процедуру.
б) сделать явную проверку наличия таблиц в базе. если таблиц нет, то вызвать процедуру создания.
г) вынести SQL-запросы в отдельный .sql файл.

Ну а в целом ты молодец =)
Советую перевести комменты на английский и выложить в общий доступ например в гугловском репозитории.
И через какое-то время сообщество поспособствует развитию твоей статистики.
Кто-то сообщит о багах, кто-то пришлёт доработки и так далее.
Mkdir
И еще одно замечание.
Раз ты используешь темплейтор, то не генерируй HTML в логике.
У тебя ссылки генерируются в логике почему-то.
Поручи этот момент темплейтору. Тем более что cheetah позволяет делать условия.
Кстати cheetah очень хороший выбор как по мне )))
Mkdir
asv13
Не устраивает быстродействие, ранее была программа - только python без всех этих наворотов с конфигами и SQL, но захотелось гибкости и вот получаю тормоз.
Прогони профайлером и узнай слабые моменты в скорости.
Моё предположение - использование cheetah без компиляции шаблонов.
На каждый запрос cheetah заново компилирует шаблоны в python-код и запускает его.
Поищи в документации как делается кеширование компилированных темплейтов.
asv13
Все обозначенное верно. Обычно когда не спешу, пробелы ставлю для красоты.

г) вынести SQL-запросы в отдельный .sql файл. - так они же в отдельном конфиге к программе?

У тебя ссылки генерируются в логике почему-то. - да, полумера - так было быстрее сделать чем передавать массив. нелогично конечно, оформление попадает в код проги. Скомпиллированный под p2.5 _namemapper.pyd не повысил скорость на глаз.

использование cheetah без компиляции шаблонов - если это возможно для программы которая работает как отдельный exe, надо посмотреть.

генерация тысяч 4кб файлов - это также вызовы большого кол-ва несложных SQL запросов. Достаточно ли они оптимальны, может возможна более “быстрая” организация таблиц.

Радикально было бы сделать всё под apache - но в этом направлении еще не видел mod_python для версии 2.5, а откатывать на 2.4 не хочется. Да и на php подобных прог много, написанных не за пару недель. Но там часто специально делают код нечитабельным, извращение без переноса строк и с переменными вида $C72h3874h ))
slav0nic
и не юзай табы В)
Mkdir
asv13
Обычно когда не спешу, пробелы ставлю для красоты.
Пробелы нужно автоматически расставлять, независимо от того спешишь или нет )
Это должно войти в автоматизм.

asv13
У тебя ссылки генерируются в логике почему-то. - да, полумера - так было быстрее сделать чем передавать массив.
Передавать массив - не единственный вариант.
Если твой темплейт отнаследуется от какого либо класса, который находится в логике, то в темплейте можно обратиться к методам через $self.blablabla()

Например в логике у тебя есть файл Main.py содержащий:
class Main:
    def getList(self):
        return [1, 2, 3, 4, 5]

В самом начале темплейта пишешь:
#extends Main
Это будет равнозначно если бы ты написал в питоне:
from Main import Main
Ну и затем можешь обращаться к этому методу следующим образом:
#for item in $self.getList():
$item<br />
#end for
И ничего передавать не нужно.

asv13
генерация тысяч 4кб файлов - это также вызовы большого кол-ва несложных SQL запросов. Достаточно ли они оптимальны, может возможна более “быстрая” организация таблиц.
Оптимизировать всегда можно. И организацию таблиц и сами запросы.
Помог бы, но у меня нет времени вникать, если честно.

P.S.: Как правильно заметил slav0nic табы использовать - грех. Настрой в редакторе чтобы вместо таба он вставлял 4 пробела.
asv13
Сделал создание template объектов через словарь, при этом компиляция происходит при первом заполнении.

if not tmpl.has_key(tmpl_name):
tmpl = Template(file = tmpl_name, filter = EncodeUnicode)
Скорость не повысилась.
Посмотрел cPrfofile
Ordered by: internal time
List reduced from 808 to 10 due to restriction <10>

ncalls tottime percall cumtime percall filename:lineno(function)
251 222.948 0.888 223.600 0.891 {method 'execute' of 'sqlite3.Cursor' objects}
122 34.411 0.282 34.411 0.282 {method 'executescript' of 'sqlite3.Cursor' objects}
1 0.842 0.842 214.245 214.245 logger.py:527(save_pl)
247 0.812 0.003 0.812 0.003 {method 'fetchall' of 'sqlite3.Cursor' objects}
242 0.619 0.003 2.220 0.009 __My_0__Myprog__COD_LOG_COD_SQL__COD_Templ_gamer_tab_tmpl.py:68(respond)
74638 0.445 0.000 1.050 0.000 logger.py:483(filter)
93482 0.324 0.000 0.324 0.000 {Cheetah._namemapper.valueFromFrameOrSearchList}
Mkdir
Оптимизировать всегда можно. И организацию таблиц и сами запросы.
Создал индексы в таблицах по основным полям. Размер базы вырос в 1.5 раза - скорость увеличилась на 13%. До этого на запрос уходило более секунды. Осталось попробовать избавиться от директив VIEW (они обновляются с каждым вызовом) - создавать временные таблицы, что не очень элегантно. Больше идей нет пока.

Mkdir
P.S.: Как правильно заметил slav0nic табы использовать - грех. Настрой в редакторе чтобы вместо таба он вставлял 4 пробела.
Я подумал это шутка, чем табы плохи )) Надо SciTE настроить.
slav0nic
asv13
вам же сказали, читайте РЕР8 )
не все юзают скайте, в других может съехать код, да и “стандарт” в питоне таб==4 пробела
asv13
slav0nic
вам же сказали, читайте РЕР8 )
прочел, все из-за несовместимости настроек редакторов.
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