Python

Posted by admin

Вибачаюсь, вибачаюсь, вибачаюсь (.

В недавній статті щодо штучного інтелекту я зробив маленьку помилку в прогі, яка давала змогу мені вигравати. Бага була в тому що він не навчався на помилка, а лише навчався на перемегах, що було не досить ефективно. Тож тепер можу вам показати скриптик, який майже НЕПЕРЕМОЖНИЙ!

Оце кусок який відповідає за логіку:

class Game(object):
    memory = one_game = {}

    def __init__(self, sticks_count):
        self.sticks_count = sticks_count
        for _ in xrange(self.sticks_count+1):
            self.memory[_] = {1:1, 2:1, 3:1}

    def finish_lose(self):
        self.memory[ min(self.one_game) ][self.one_game[ min(self.one_game) ]] -= 1

    def one_move(self, stick):
        ch = []
        for i in self.memory[stick]:
            for _ in xrange(self.memory[stick][i]):
               ch.append(i)
        if not ch:
            return 1
        self.one_game[stick] = random.choice( ch )
        return self.one_game[stick]
Continue reading...
Posted by admin

Життя інколи дарує нам випробування. Коли до вас доходить звістка, що "на вашому сервер згорів вінчестер", то таке випробування ой як складно подолати. Але якщо ми підготовлені, то нам нічого буде хвилюватися ).

Найголовніше що є на сервері це База Данних, і налаштувати її бекап на Лінуксі досить просто одним маленьким шел-скриптом, а от з віндовсом трішки треба помучитися, але я вже помучився за вас. Вам лише досить скопіювати цей скрипт на Пітоні і поставити його в Планувальних Задач. Його функціонал складається лише з створення дампа бази данних і послідуючої архівації:

import os
from time import gmtime, strftime
import subprocess
import zipfile

mysql_user = 'root'
mysql_pwd = '12345'
mysql_db = 'super_puper_db'
dump_dir = 'c:\\temp\\'

dump_file = "mysqldump-" + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
dump_file_zip = dump_file+'.zip'
dump_file += '.sql'

subprocess.call("mysqldump --user " + mysql_user + " --password=" + mysql_pwd + " --force --flush-privileges --compress --comments " + mysql_db + " > " + dump_dir + dump_file, shell=True)

zf = zipfile.ZipFile(dump_dir+dump_file_zip, 'w', allowZip64=True)
zf.write(dump_dir+dump_file, dump_file, zipfile.ZIP_DEFLATED)
zf.close()

os.remove(dump_dir+dump_file)
Posted by admin

Цей простий алгоритм штучного інтелекту знав ще зі школи. Про нього було написано в якійсь радянській книжечці типу "Наука і Техніка". Тож після десятирічь забуття, про нього згадав після наступної статті на Хабрі - http://habrahabr.ru/blogs/artificial_intelligence/84125/ (раджу прочитати зараз).

Позавчора ввечері потратив аж півгодинки свого часу і в результаті вийшов скриптик на пітоні з 75 строчок(хоча сам алгоритм гри лише 30 строчок), що реалізує цей алгоритм. Що найдивовижніше - це те що воно ще й працювало )

Зняв відео про це, точніше кажучи зняв 2 відео, бо перше не сподобалося, але потім здуру на Вімео залив першу поганеньку версію, за що вибачаюсь, і прийдеться терпіти мій сонний голос :)

Self-Education Python Script from presidentua on Vimeo.

Continue reading...
Posted by admin

Моя стаття з 12 випуска журналу Хакер, як завжди з помилками, і без виправлень.

Троянский Змей

Сказ о троянописании на Python'e

Когда-то Лёня Да Винчи скачал "Существует три разновидности людей: те, кто видит; те, кто видит, когда им показывают; и те, кто не видит". Но в наше время я бы еще добавил группу - те кто видят все, когда им это нужно. Чтобы в ней быть, нужно уметь получать любую информацию - это умение и будем развивать с помощью Python.

Continue reading...
Posted by admin

Ви напевно знаєте такий тип змінних як static, які містяться в функціях і їхнє значення зберігається між викликами функцій. Якщо згадувати пенсіонера С, то приклад буде такий:

function example1(void) {
   static int A = 1;
   A++;
   print('A = '+A);
}
example1();
>> A = 2
example1();
>> A = 3
example1();
>> A = 4

Думаю цей код працювати не буде через моє незнання С, але суть показує. І повертаючись до мого любимого Python'а - в ньому таких статичних методів в функціях немає, і замість того треба юзати класи:

class S(object):
    a = 1
def example2():
    S.a += 1
    print "a = "%(S.a)
example2()
>> a = 2
example2()
>> a = 3
example2()
>> a = 4

Я постійно використовую таку функціональність, але незнав до недавнього часу особливість, що варта була декількох годин відладки коду. Отже, хай ви класи і їхні властивості будете використовувати як "ключ"(флажок) для неповторення функціоналу. Наприклад так:

class S(object):
    was_run_example2 = False
def example2()
    if not S.was_run_example2:
        print "PRINT ONLY ONE"

example2()
>> PRINT ONLY ONE
example2()
example2()
example2()

Тепер ми прийшли до суті, мій модуль для логування в Пітоні використовує приблизно таку систему(хоча код набагато там кращий:) ), щоб налаштовувати логування лише раз. Але нещодавно виявилось, що почали дублюватися логи, тобто якимось чином ця система не працювала і код налаштування логування викликався 2 рази. Довго я не міг зрозуміти навіть приблизну причину, і тестував все методом "наукового тика" - постійно коментуючи різні участки кода і дивлячись чи було дублювання чи ні. Нарешті виявилось, що якщо цю функцію інклудити по різному в Пітоні, то для Пітона це буде два різні файли і різні обьєкти з різними значеннями полів обьєкту:

include example2
from utils include example2
from project.utils include example2

Звичайно в одному файлі так не напишете, але якщо це багатомодульна система, то досить легко завантажити в якийсь момент її по іншому і в результаті з'явиться помилка яку не так і легко знайти.

Надіюсь що ви не будете наступати на ці граблі, як я наступив )

Posted by admin

Перед тим як зайти в глибоке святкування Нового Року вирішив написати два поста, один технічний, а інший про результати 2009 року. Тож щодо технічного, то одна з найважливішої функції в будь-якій системі - є її моніторинг - можливість бачити що де й як проходить, чи бувають помилки і якщо так, то де саме. Поскільки я програмую на Пітоні й Джанго, то мова буде саме про цею парочку.

Отще в Пітоні є чудернатський модуль logging, що дає можливість логувати різні за типом події. Найпростіша робота з ним це:

import logging
logging.info('info message')
logging.error('error messaqge')

Найпростіший спосіб, але я його не юзаю, бо не дуже прикольно працювати зі стандартним потоком повідомлень, а краще юзати окремий, щоб чужі модуля не могли до нього нічого писати:

import logging
log = logging.getLogger('log')
log.error('error messaqge')

Тепер в нас є власний потік повідомленнів, але крім того що він є, його треба й виводити кудись, зберігати, то для цього на нього навішуються різні обробники. Ось наприклад навісим, що все виводилось в консоль:

formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setFormatter(formatter)
stream_handler.setLevel(logging.DEBUG)

log.addHandler(stream_handler)
Continue reading...
Posted by admin
Моя стаття з 11-номеру журнала Хакер в оригіналі зі всіма помилками.

Пишем на Python'e снифер используя Google App Engine

Представлял ли ты когда-нибудь, что Google будет ловить лично для тебя сессии пользователей и тем помогать "исследовать", к примеру, чужие почтовые аккаунты? Я тоже нет, пока не появился Google App Engine. Сегодня затестим его создавая супер-крутой снифер.

В моей статье за прошлый месяц с тобою обсудили некоторые сервисы Гугла, но один я сознательно оставил на отдельную статью. Ведь Google App Engine(GAE) одна из перспективнейших масштабируемых "облачных" технологий, которую можно бесплатно заюзать. Это такой себе крутой хостинг, что автоматически увеличивает свою "скорость" в зависимости от количества юзеров. Если сегодня у нас 100 юзеров, то хостинг работает. Если завтра придет еще 1 миллион сверху, то Гугл автоматически подкинет серверов, и все будет также стабильно. Еще в GAE есть куча дополнительных API по работе с базой данных, memcache, почтой, джабером, также огромным плюсом является возможность бесплатного использования (правда с некоторыми мелкими ограничениями). Поэтому нам не затестить такую штуку прям грех ;)

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

Continue reading...
Posted by spirit

Захотілося мені, щоб на сайті відображалався номер ревізії меркуріала, на основі якої зроблений deploy(перенесення скриптів на сервер).

Спочатку думав навісити хук до меркуріала, але вирішив піти легшим шляхом, як завжди. ;))). І переписав мій скрипт для деплою. Отож раніше мій скрипт(deploy.bat) для деплою був наступний:

rmdir /S /Q temp
mkdir temp

cd temp
hg clone d:\avcheck
... тут викликаються ще декілька пітоновський скриптів
... результат закидається на сервер
Тож щоб дістати номер ревізії додав такі рядки:
cd ..
hg log --limit 1 >  ./deploy/temp/rev.txt
cd deploy
які дістають опис останньої ревізії і зберігають його в файл deploy/temp/rev.txt

Далі в deploy.bat додав, щоб в кінці запускався пітоновський скрипт, що парсить файл rev.txt, дістає номер ревізії і зберігає його в Джанговський конфіг:

import re

with open('./temp/rev.txt', 'r') as fr:
    rev = fr.readline().split(':')[1].strip()
    if int(rev) < 0:
        print "error rev"
        exit

with open('./temp/avcheck/avcheck/settings.py', 'r+') as fs:
    file_origin = fs.read()
    fs.seek(0)
    fs.write(file_origin)
    file_new = re.sub("REVISION_NUMBER = \d*", "REVISION_NUMBER = "+rev, file_origin)
    fs.write(file_new)
Тепер в мене завжди на сайті показується внизу номер ревізії ;)
Posted by spirit
Перша моя стаття з циклу про програмування Google, що була опублікована в журналі Хакер. Тут як завжди повна версія з помилками ;)

Наша "Империя зла"

Учимся покорять Google с использованием Python

Многие называют Google "корпорацией зла", хотя я и не вижу в ней ничего плохого, но если народ называет, так тому и быть. И для превращения Google действительно в "зло" научимся использовать его сервисы для своих ооочень благородных хакерских дел.

Continue reading...
Posted by spirit

Не встигло чорнило висохнути з минулої статті про робота для Гугло Хвилі, як наразі ще один робот народився в недрах UASC і готовий вийти в паблік.

Тож, прошу вітати - wabber-robot. Назва якого пішла від слів wave jabber robot. Роглянемо, що ж він робить. Він живе по адресу wabber-robot@appspot.com, і якщо додасте його в список контактів, а потім на якусь хвилю, то він додасть на хвилю таке повідомлення:

I'm alive!
Command:
wabber-bot add me: jabber@jabber.ja
wabber-bot remove me: jabber@jabber.ja
В цім невеличкому повідомлення можна розшифрувати, що якщо ви напишете команду "wabber-bot add me: ваш@джабер", то ви свій джабер прикріпете до цієї хвилі. І далі всі нові повідомлення в хвилі будуть приходити й на ваш джабер. Коли надоїсть це вам, то можете скористуватися командою: "wabber-bot remove me: ваш@джабер". Як бачимо все банально.

А якщо ж забажається глянути неоптимізований код із аж 70 рядків, то його знайдете по адресу: http://bitbucket.org/presidentua/wabber-robot/.

Enjoy!