Главная страница  Карта сайта  Печать  Написать письмо  RSS
Войти
Кнопка открытия главного меню
Персональный сайт
Стеллецкого Владимира
Обновленные страницы
01.01.2025
О сайте
29.12.2024
Живой журнал
20.12.2024
Авто

ещё

Новые комментарии
28.12.2024 11:43
swi
26.12.2024 10:44
swi (отвечено)
23.12.2024 21:56
swi (отвечено)

ещё

Случайная страница

Ё-моё

Обновлено: 22.12.2023 г.

Python

В 2009 году я решил изучить ещё какой-нибудь язык программирования. После анализа текущего выбора языков программирования я остановил свой выбор на Python или Ruby. После ещё некоторых колебаний склонился всё же к Python. Может быть когда-нибудь и до Ruby руки дойдут.

Если обнаружите ошибки или сможете предложить более "правильное" решение размещённых здесь задач, или же какую-то задачку для решения - пишите, буду очень признателен.

Ссылки (18.12.2019) #

« первая   ‹ предыдущая   1   2   3   ›  »

Транспортный налог (18.10.2012) #

В связи с обсуждаемым изменением ставки транспортного налога в г. Москве, набросал крошечный скрипт для его расчета по текущим и обещанным (новым) ставкам:

  1. #-*- coding: utf-8 -*-  
  2. tnc = list()  
  3. tnc.append((000))  
  4. tnc.append((70712))  
  5. tnc.append((1002025))  
  6. tnc.append((1253035))  
  7. tnc.append((1503845))  
  8. tnc.append((1754550))  
  9. tnc.append((2006065))  
  10. tnc.append((2257575))  
  11. tnc.append((250150150))  
  12. tnc.append((410150300))  
  13.   
  14. while True:  
  15.     title = u'Введите количество лошадиных сил (или ENTER для выхода): '  
  16.     print title  
  17.     title_e = 'Enter the amount of horsepower (or ENTER to exit): '  
  18.     s = raw_input(title_e)  
  19.     if s == '':  
  20.         break  
  21.     x = int(s)  
  22.     for c in tnc:  
  23.             if x > c[0]:  
  24.                     c1 = c  
  25.             else:  
  26.                     break  
  27.     print u'Транспортный налог для %s "лошадей" был %s р., станет %s р. (+%s р.) n' % (x, x*c1[1], x*c1[2], x*(c1[2] - c1[1]))  

Pythonic (15.03.2012) #

Начал читать книгу Дэвида М. Бизли - Python. Подробный справочник. Идёт не очень быстро, зато, кажется, стал проникаться философией питона - pythonic (подробнее здесь или здесь). Действительно хочется красивых и элегатных решений, тем более что для этого все предоставлено.

Как первый шаг удалось значительно упростить давнее (см. ниже), но периодически используемое решение, которое позволяет с легкостью реализовывать таблицы с историей изменений данных (изменённую версию опубликую чуть позже).

History к таблице (24.01.2010) #

Довольно часто стала возникать задача сделать историю изменений для какой-либо таблицы на MS SQL-сервере. У нас это реализуется путем создания дополнительной таблицы, содержащей все поля базовой + собственный идентификатор (H_ID) и тип операции вставка/обновление/удаление. Для записи в неё на базовой таблице создаются три триггера: after insert/update/delete, в которых осуществляется копирование данных. Делать каждый раз "руками" мне было лень, и я написал следующий скрипт:

  1. # -*- coding: utf-8 -*-  
  2. import _mssql  
  3.   
  4. import sys  
  5. class error:  
  6.     def write(self, text):  
  7.         open('error.log''a').write(text)  
  8. sys.stderr = error()  
  9.   
  10. print u"2009 Stelletsky V. "  
  11. print u"Таблицы истории и триггеров"  
  12. print  
  13. #t = u"Название таблицы: "  
  14. tbname = raw_input("Table Name: ")  
  15. if tbname == "":  
  16.     sys.exit(1)  
  17.   
  18. conn = _mssql.connect(server='servername', user='username', password='password', database='databasename')  
  19. # проверка существования таблиц  
  20. st = "SELECT * FROM INFORMATION_SCHEMA.TABLES "  
  21. st = st + "WHERE TABLE_NAME IN ('" + tbname + "', '" + tbname + "_H') ORDER BY TABLE_NAME"  
  22. conn.execute_query(st)  
  23. i = 0  
  24. for row in conn:  
  25.     if tbname <> row['TABLE_NAME'and i==0:  
  26.         print u"Таблица %s не найдена!" % (row['TABLE_NAME'])   
  27.         raw_input("Done")  
  28.         sys.exit(1)  
  29.     if tbname + "_H" == row['TABLE_NAME'and i==1:  
  30.         print u"Таблица %s уже создана!" % (row['TABLE_NAME'])   
  31.         raw_input("Done")  
  32.         sys.exit(1)  
  33.     i = i + 1  
  34. if i == 0:  
  35.     print u"Таблица '%s' не найдена!" % (tbname)   
  36.     raw_input("Done")  
  37.     sys.exit(1)  
  38.   
  39. print u"Создание таблицы %s" % (tbname + '_H')  
  40. st =      "SELECT * FROM INFORMATION_SCHEMA.[COLUMNS] c "  
  41. st = st + "WHERE c.TABLE_NAME = '" + tbname + "' "  
  42. conn.execute_query(st)  
  43. st = "CREATE TABLE [dbo].[" + tbname + "_H] ("  
  44. st = st + " [H_ID] int IDENTITY(1, 1) PRIMARY KEY NOT NULL, "  
  45. st = st + " [Operand] varchar(1) NOT NULL "  
  46. st_f = ""  
  47. for row in conn:  
  48.     st = st + ", "  
  49.     st_f = st_f + ", [" + row['COLUMN_NAME'] + "]"  
  50.     st = st + " [" + row['COLUMN_NAME'] + "] " + row['DATA_TYPE']   
  51.     if row['CHARACTER_MAXIMUM_LENGTH'] <> None:  
  52.         st = st + "(" + str(row['CHARACTER_MAXIMUM_LENGTH']) + ") "  
  53.     if row['COLLATION_NAME'] <> None:  
  54.         st = st + "COLLATE " + row['COLLATION_NAME']  
  55.     if row['IS_NULLABLE'] == "NO":  
  56.         st = st + " NOT"  
  57.     st = st + " NULL"  
  58. st = st + ")"          
  59. conn.execute_non_query(st)  
  60. print u"Создание триггеров"  
  61. i = 0  
  62. while i < 3:  
  63.     if i == 0:   
  64.         st_o = "I"  
  65.         st_op = "INSERT"  
  66.         st_from = "inserted"  
  67.     elif i == 1:  
  68.         st_o = "U"  
  69.         st_op = "UPDATE"  
  70.     elif i == 2:  
  71.         st_o = "D"  
  72.         st_op = "DELETE"  
  73.         st_from = "deleted"  
  74.     st =      "CREATE TRIGGER [dbo].[" + tbname + "_A" + st_o + "] ON [dbo].[" + tbname + "] "  
  75.     st = st + "WITH EXECUTE AS CALLER "  
  76.     st = st + "FOR " + st_op + " "  
  77.     st = st + "AS "  
  78.     st = st + "BEGIN "  
  79.     st = st + "  INSERT INTO dbo.[" + tbname + "_H] "  
  80.     st = st + "  (Operand" + st_f + ") "  
  81.     st = st + "  SELECT "  
  82.     st = st + "  '" + st_o + "'" + st_f + " "  
  83.     st = st + "  FROM " + st_from + " "  
  84.     st = st + "END "  
  85.     conn.execute_non_query(st)  
  86.     i = i + 1  
  87.       
  88. raw_input("Done")  

Создание таблицы на MSSQL-сервере (13.11.2009) #

В связи со сменой работы, пропала возможность пользоваться конструктором для создания таблиц в БД. Решил реализовать необходимый мне сейчас функционал на Python. А заодно попробовать запрограммировать GUI с помощью библиотеки PyQt4. Пока реализовано только "консольное" приложение, создающее таблицу на MS SQL сервере с некоторым количеством "стандартных" полей (ID, Parent_ID, Del, Role_ID, DateChange). Количество и названия создаваемых полей легко изменить:

  1. # -*- coding: utf-8 -*-  
  2. import _mssql  
  3.   
  4. import sys  
  5. class error:  
  6.     def write(self, text):  
  7.         open('error.log''a').write(text)  
  8. sys.stderr = error()  
  9.   
  10. print u"2009 Stelletsky V. "  
  11. print u"Создание таблицы"  
  12. print  
  13. #t = u"Название таблицы: "  
  14. tbname = raw_input("Table Name: ")  
  15. if tbname == "":  
  16.     sys.exit(1)  
  17.   
  18. needpid = raw_input("Need Parent_ID (Y/N): ")  
  19. print u"Создание таблицы", tbname  
  20. # запрос на создание таблицы  
  21. st = "CREATE TABLE "  
  22. st = st + "[dbo].[" + tbname + "] ("  
  23. st = st + "[ID] int IDENTITY(1, 1) NOT NULL PRIMARY KEY, "  
  24. if needpid=="y" or needpid=="Y":  
  25.     st = st + " [Parent_ID] int DEFAULT 0 NOT NULL, "  
  26. st = st + " [Del] bit DEFAULT 0 NOT NULL, "  
  27. st = st + " [Role_ID] int NULL, "  
  28. st = st + " [DateChange] datetime NULL"  
  29. st = st + ")  "  
  30.   
  31. try:  
  32.     conn = _mssql.connect(server='servername', user='username', password='password', database='databasename')  
  33.     conn.execute_non_query(st)  
  34. except _mssql.MssqlDatabaseException,e:  
  35.     if e.number == 2714 and e.severity == 16:  
  36.         print u"Tаблица", tbname, u"уже существует!"  
  37.     else:  
  38.         raise # re-raise real error  
  39. finally:  
  40.     conn.close()  
  41. raw_input("Done")  

Парсер характеристик прицепов (04.09.2009) #

Появилась необходимость в прицепе. Выбирая наткнулся на сайт с огромным выбором, но на нём все прицепы для грузов свалены в одну кучу. Решил написать python-скрипт для разбора в Excel читаемый вид характеристик прицепов для последующего анализа и выбора. Заодно удалось потренироваться в программировании на Python. Все необходимые файлы, включая исходный текст программы и уже обработанный Excel с характеристиками прицепов можно найти здесь (27 kb).

Удаление PHPSESSID (14.04.2009) #

Если при построении моего сайта происходит какая-либо ошибка, то информация о ней сохраняется в таблицу err. Часто в ссылках встречается PHPSESSID, который мне не нужен и несколько мешает просматривать сообщения. Вот простенький скрипт убирающий его:

  1. #-*- coding: utf-8 -*-  
  2. import MySQLdb  
  3.   
  4. print u"2009 Stelletsky V. "  
  5. print u"Удаление PHPSESSID из таблицы errors"  
  6. print  
  7. # Соединение с БД  
  8. db = MySQLdb.connect(host='host', user='user', passwd='pass', db='database')    
  9. db.set_character_set('utf8')  
  10. query = 'SELECT ID, URL FROM `err`'  
  11. cursor = db.cursor()  
  12. cursor.execute(query)  
  13. result = cursor.fetchall()  
  14. k = k1 = 0  
  15. for record in result:  
  16.     s = unicode(record[1], 'utf-8')  
  17.     n = s.find('PHPSESSID')  
  18.     k+=1  
  19.     if n >0:  
  20.         k1+=1  
  21.         cursor.execute("""UPDATE `err` SET Message = %s WHERE ID = %s """, [(s[:n-1] + s[n+42:]), record[0]])  
  22. print u"Всего " + str(k) + u", обработано " + str(k1)  
  23. raw_input("Done")  

Рисование графика (03.11.2009) #

Постоянные посетители знают, что на странице О сайте можно посмотреть график запросов страниц сайта за последние несколько месяцев. Для его получения я каждый месяц в ручную выполнял запрос в базу данных сайта, полученное значение переносил в Excel, потом диаграмму с графиком сохранял в формате png, и закачивал на сайт. Получился прям целый ритуал, который мне порядком надоел, и я решил его автоматизировать, а раз уж взялся за изучение Python, то и реализовать решил на нём. Вот что у меня получилось.

  1. #-*- coding: utf-8 -*-  
  2. import MySQLdb  
  3. import aggdraw  
  4. from PIL import Image, ImageDraw, ImageFont  
  5. mon = (u"Янв", u"Фев", u"Мар", u"Апр",  
  6.        u"Май", u"Июн", u"Июл", u"Авг",  
  7.        u"Сен", u"Окт", u"Ноя", u"Дек")  
  8. graphcolors = ("red""green""blue")  
  9. y_steps = (20050010002000500010000)  
  10.   
  11. xcw = 50 # ширина ячейки  
  12.   
  13. # Соединение с БД  
  14. db = MySQLdb.connect(host='host', user='user', passwd='pass', db='database')  
  15. query = 'SELECT `Counter` FROM `stat`'  
  16. cursor= db.cursor()  
  17. cursor.execute(query)  
  18. result = cursor.fetchall()  
  19. maxval = 0  
  20. minval = 1000000  
  21. for record in result:  
  22.     if record[2] > maxval:  
  23.         maxval = record[2]  
  24.     if record[2] < minval:  
  25.         minval = record[2]  
  26. # временно отключаем ограничение шкалы графика по минимальному значению  
  27. minval = 0  
  28. delta = (maxval - minval) / 10  
  29. # округляем до большего кратного  
  30. for i in y_steps:  
  31.   if delta < i:  
  32.     delta = i  
  33.     break  
  34. # диапазон для вывода графика  
  35. min_gr = 0  
  36. for i in range(100):  
  37.     if i*delta < minval:  
  38.        min_gr = i*delta  
  39.     if i*delta > maxval:  
  40.        max_gr = i*delta  
  41.        break  
  42. lcount = i  
  43. # получение масштаба по Y  
  44. m_y = 430.0 / (max_gr - min_gr)  
  45. # рисование  
  46. #image = Image.new("RGBA", (660,480), (255,255,255,255))  
  47. image = Image.new("RGB", (660,480), "white")  
  48. draw = aggdraw.Draw(image)  
  49. draw.setantialias(False)  
  50. apen = aggdraw.Pen("#999"1)  
  51. apen1 = aggdraw.Pen("#ddd"1)  
  52. draw.line((50,20,50,450), apen)  
  53. draw.line((50,450,650,450), apen)  
  54. arial = aggdraw.Font('#333'"C:\WINDOWS\Fonts\arial.ttf"12)  
  55. # Черточки и подписи на оси X  
  56. for i in range(13):  
  57.     draw.line(((50+xcw*i),446,(50+xcw*i),454), apen)  
  58.     if i > 0:  
  59.         draw.line(((50+xcw*i),450,(50+xcw*i),20), apen1)  
  60.     if i < 12:  
  61.         draw.text((65+xcw*i, 455), mon[i], arial)        # подписи  
  62. #draw.line(((50+50*12),446,(50+50*12),454), apen)  
  63.   
  64. # Рисование чёрточек на Y  
  65. for i in range(lcount+1):  
  66.     draw.line((48,(450-delta*m_y*i),52,(450-delta*m_y*i)), apen)  
  67.     if i > 0:  
  68.         draw.line((50,(450-delta*m_y*i),650,(450-delta*m_y*i)), apen1)  
  69.     st = str(min_gr+i*delta)  
  70.     a = draw.textsize(st, arial)  
  71.     draw.text(((45 - a[0]), (443-delta*m_y*i)), st, arial)  
  72.   
  73. # Рисование  графика  
  74. draw.setantialias(True)  
  75. grColor = -1  
  76. x = y = 1  
  77. pyear = -1     # предыдущий год  
  78. px = py = -1  # предыдущие координаты  
  79. for record in result:  
  80.     # настройка цветов  
  81.     if int(record[0])<> pyear:  
  82.         pyear = record[0]  
  83.         grColor += 1  
  84.         px = py = -1  
  85.         abrush = aggdraw.Brush(graphcolors[grColor])  
  86.         apen = aggdraw.Pen(graphcolors[grColor], 2)  
  87.     x = 25 + xcw * int(record[1])  
  88.     y = 450 - (int(record[2]) - min_gr) * m_y  
  89.     draw.rectangle((x-2, y-2, x+2, y+2), apen, abrush)  
  90.     # соединяем с  предыдущей точкой  
  91.     if px <> -1 and py <> -1:  
  92.         draw.line((px, py, x, y), apen)  
  93.     px = x  
  94.     py = y  
  95. #    print record[0], "-->", record[1], "-->", record[2]  
  96. print minval, maxval, delta, min_gr, max_gr, lcount, m_y  
  97.   
  98. draw.flush()  
  99. image.save("test.png""PNG")  
  100. raw_input("Done")  

Здесь приведён не окончательный вариант скрипта. Я его ещё дописываю, так как есть некоторые недостатки:

  1. Графику не хватает легенды;
  2. Скрипт не умеет загружать файл на сервер. Возможно загрузку на FTP делать не буду, а просто размещу скрипт на web-сервере.
  3. Получаемая картинка большая по объему (около 30кб), так как указана палитра в 256 бит. Но само изображение можно без видимой потери качества конвертировать до глубины цвета 4 бита, тогда изображение становится около 5кб, что приятно.

Из-за использования сторонних библиотек для работы с графикой и соединения с MySQL, пришлось отказаться от использования последней версии Python и ограничится версией 2.5.4. Несмотря ни на что, данный скрипт упростил мне работу. Новый вариант графика можно просмотреть на странице о сайте, а старый "ручной" вариант здесь.

Комментарии

swi, www (06.03.2009)
Да, но на графиках я января и февраля так и не увидел...
Странно. Возможно браузер отобразил картинку из кэша. На новом графике данные за январь и февраль показаны красным.

« первая   ‹ предыдущая   1   2   3   ›  »

  Вы 20 725 посетитель этой странички
с 05 марта 2009 года
© http://svv-home.ru
О сайте