Monthly Archives: Березень 2012

Найпростіший спосіб вимірювання найгіршої метрики

Або іншими словами – примітивний облік робочого часу в лінуксах.

Для цього є команда – last. Дозволяє подивитись в логах час останніх входів і виходів з системи. Якщо наприклад дати команду

last 7 # еквівалентно last tty7

Дізнаємось хто коли і скільки користувався сьомим терміналом:

bunyk    tty7         :0               Thu Feb  2 08:30 - down   (09:32)

Вдома попробував – не працює. А виявляється все тому, що є певна конфігурація ротації логів /etc/logrotate.conf, в якій написано – monthly.

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

А ще збацав коротенький скриптик, який бере дані з last, і рахує середній робочий час:

#!/usr/bin/python3
import re
import subprocess 

def hours(s):
    s = s.split(':')
    return float(s[0]) + float(s[1]) / 60

def to_str(x):
    h = int(x)
    m = 60 * (x - h)
    return '%s:%s' % (h, int(m))

output = subprocess.check_output(['last', '7']).decode('utf-8')

data = (re.findall(r'\((\d\d:\d\d)\)', x) for x in output.splitlines())
data = [hours(x[0]) for x in data if x]

print(output)
print('Average time: ', to_str(sum(data)/len(data)))

bunyk@bunyk-laptop:~/workspace/uaprom$ /home/bunyk/experimental/timestat.py 
bunyk    tty7         :0               Thu Mar 22 09:32   still logged in   
bunyk    tty7         :0               Wed Mar 21 10:37 - 19:51  (09:13)    
bunyk    tty7         :0               Tue Mar 20 11:48 - down   (08:16)    
bunyk    tty7         :0               Mon Mar 19 11:38 - down   (07:14)    
bunyk    tty7         :0               Sat Mar 17 09:45 - down   (08:36)    
bunyk    tty7         :0               Fri Mar 16 10:35 - 19:23  (08:48)    
bunyk    tty7         :0               Thu Mar 15 10:22 - down   (08:47)    
bunyk    tty7         :0               Tue Mar 13 10:02 - 19:44  (09:42)    
bunyk    tty7         :0               Mon Mar 12 12:08 - 20:34  (08:25)    
bunyk    tty7         :0               Wed Mar  7 10:29 - down   (07:42)    
bunyk    tty7         :0               Tue Mar  6 09:54 - down   (09:50)    
bunyk    tty7         :0               Mon Mar  5 11:15 - 19:32  (08:16)    
bunyk    tty7         :0               Sat Mar  3 11:21 - down   (07:03)    
bunyk    tty7         :0               Fri Mar  2 12:08 - down   (08:00)    

wtmp begins Thu Mar  1 18:46:07 2012

Average time:  8:27

Виходить що я трохи більше ніж пів-години на добу недопрацьовую. Правда шпигунський роман Тоні ДеМарко розповідає про те що до програмістів краще не застосовувати метрики, бо ті хитрі зарази знайдуть спосіб максимізувати метрику не покращуючи продукт. Якою гарною ця метрика не була б (хай навіть зміною відношення кількості вад до кількості функціоналу). А Тоні ДеМарко – виявляється в вікіпедії стоїть поруч з такими гігантами як Вард Каннінгам, Мартін Фаулер і навіть Тоні Хоар. Напевне варто познайомитись детальніше. Правда часу нема. Але якщо він не важливий, тоді важливе лише те що я вважаю важливою дією в кожен момент часу.


Filed under: Інструменти, Кодерство Tagged: linux, робота, Python

Кібернетична вікі. Епізод II. Атака ботів

Не так давно
на одному
сервері кібцентру…

В Кібернетичній вікі
неспокійно. Більше сотні
користувачів демонструють
наміри закидати її спамом.

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

Адміністрато bunyk повертається в КібВікі
щоб зайнятись принциповим питанням: створенням
бота для допомоги джедаям в малоуспішній боротьбі…

Пафосні титри подивились – переходим до банального сюжету про те як добро перемогло зло. :) Зі мною була нова сила (Python 3), і розуміння того що об’єктно-орієнтоване програмування призначене для зменшення кількості подібних параметрів в різних методах. І знання PEP8 яке дозволяє писати код на 8 та більше балів за Пайлінтом.

До того дії всіх ботів я відкидав вручну, слідкуючи за вікі через RSS. Коли їх було 1-2 на день це ще можна було терпіти. Але коли вони повалили десятками я на деякий час забив.

Я вирішив не морочити собі голову з PywikipediaБотом, для роботи якого на cybwiki ще треба створювати окремий файл конфігурації, а змайструвати свого. Свого писати набагато приємніше ніж лазити по сотнях файлів чужого. Крім того, мені дуже соромно за старий bunykwikibot, бо той код – блювотний. Зрозуміло що рік тому я цього не міг бачити. Тому маючи ще один день відпустки який залишився з проходження практики вирішив використати цей шанс щоб виправити ситуацію.

Знайомтесь – bunykwikibot2. Поки що різноманітних запитів до вікі в нього менше. Але зате він вміє логінитись і писати. І з ним приємно працювати.

Покажу на прикладі сьогоднішнього бою проти спамерів (ввесь код):

#!/usr/bin/python3

Ага. Рухаємось вперед. Бо якщо не ми, то хто?

from api import Wiki

Простіше простого. І не треба завантажувати штук п’ять функцій!

def hunt_bots():
    wiki = Wiki('http://cybportal.univ.kiev.ua/w/api.php')
    wiki.session_file('bunyk_on_cybwiki.session')

Це в нашого скрипта головна функція. При запуску створює новий клієнт wiki, для API за заданою адресою. Другий рядочок каже що дані сесії (куки і ще дещо) будуть завантажуватись з вказаного файлу. А якщо їх там нема – попросити в користувача залогінитись і записати туди дані сесії.

    def marked_bot(user):
        userpage = user.userpage().read() or ''
        return '{{Spambot}}' in userpage

Як розрізнити спам і не спам? Пол Грем написав статтю про Баєсівський класифікатор, а я як останній неуч її все ще не читав. Тому вирішив просто позначити всіх ботів вручну, шаблончиком {{Spambot}}. Функція вище отримує текст сторінки користувача, і дивиться чи там не написано що користувач – бот.

Зрозуміло бота ще треба позначити. Цим займається наступна функція:

    def shoot_bot(bot):
        bot.userpage().write('{{Spambot}}', 'Попався!')

Перший її рядок замінює текст сторінки бота позначкою про те що він бот, супроводжуючи цю дію бойовим криком “Попався!”.

        for contrib in bot.contributions():
            spam_page = wiki.page(contrib['title'])
            only_bots = True
            for user in spam_page.contributors():
                if not marked_bot(user):
                    only_bots = False
                    break
            if only_bots:
                spam_page.delete('Спам.')

Далі по черзі розглядаються всі сторінки які бот редагував. І якщо єдиними редакторами цих сторінок були вже позначені боти – сторінки теж видаляються.

        bot.block('Die spammers, die!')

Після цього бот блокується з іншим грізним криком.

Але основна частина скрипта – визначення хто бот, а хто ні:

    for user in wiki.all_users:
        userpage = user.userpage()
        page_text = userpage.read()
        if page_text:
            if '{{Spambot}}' in page_text:
                print(user.name, '- ботяра')
                continue
            if '{{Approved}}' in page_text:
                print(user.name, '- чесний')
                continue
            print(page_text)
        else:
            print('Сторінка користувача порожня')
        edits = user.edit_count()
        print(userpage.title, 'Редагувань: %d' % edits)

Я розглядав кожного користувача. Якщо він вже позначений – виводив повідомлення і брав наступного. Якщо ж ні – виводив текст його сторінки користувача, логін і кількість редагувань.

        if edits < 3:
            verdict = True
        else:
            verdict = ask_y_n('Це бот, як думаєте?'
                '(y/n або порожній рядок якщо не знаєте)'
            )

Спочатку кожну справу я розглядав вручну. Потім до мене якось дійшло що кожен бот залогінювався і робив не більше двох редагувань. Видно вони на більше не розраховані бо їх банять і доводиться реєструвати нові аккаунти. Правда через це мало не “постраждав” Номіровський тому що статтю про себе він редагував переважно анонімно, але я все виправив руками.

        if verdict == '':
            continue
        elif verdict:
            shoot_bot(user)
        else:
            userpage.append(
                '{{Approved}}',
                'Підтвердження того що власник сторінки - не бот.'
            )

Ну і коли сторону користувача визначено, він або розстрілювався, або позначався як наш. Якщо не визначено – пропускався.

Ну після довгої підготовки бій був коротким:
Робота бота

Результати: заблоковано 114 ботів. 40 нормальних користувачів підтверджено.

Тепер напевне пора думати що робити з наступними навалами? Банити всіх хто не поставить на свою сторінку відповідний шаблон, а анонімів за географічною ознакою? Чи таки вчити баєсівський класифікатор розрізняти дифи? Побачимо.


Filed under: Кодерство, Павутина Tagged: CybWiki, вікіпедія, Python

Небезпечні змінні об’єкти як значення аргументів функції за замовчуванням

Якось пишу я один сайт (та все той же) і натикаюсь на отаку грізну помилку:

Через деякий час знайшлась і причина помилки, і те падло яке цю причину написало:

Bunyk Fri Oct 07 13:45 2011:   def __init__(self, label=u'', validators=[
Bunyk Fri Oct 07 18:31 2011:       validators.NumberRange(min=decimal.Decimal('0.01'),
Bunyk Fri Oct 07 13:45 2011:       message=_(u"Значение должно быть больше чем %(min)s"))
Bunyk Fri Oct 07 13:45 2011:       ], **kwargs
Bunyk Fri Oct 07 13:45 2011:   ):

Ну справді, хто так пише. Дужку варто закривати на тому ж рівні вкладеності на якому вона відкривалась це раз:

def __init__(self, label=u'',
    validators=[validators.NumberRange(
        min=decimal.Decimal('0.01'),
        message=_(u"Значение должно быть больше чем %(min)s")
    )],
    **kwargs
):

І два – списки, словники та інші змінні (mutable) об’єкти не надто бажані як значення аргументів за замовчуванням.

Чому так? Тому що це уможливлює ефекти про які я зараз розповім. А ці ефекти можуть здивувати, як і повідомлення на картинці.

Як відомо, в Python все є об’єктом. Навіть функції і класи. А про будь-який об’єкт найважливіше що варто знати – це коли і як він створюється.

Тепер давайте розглянемо який-небудь сферичний код в вакуумі. Наприклад такий:

def next(line=[]):
    line.append(len(line) + 1)
    print line
    
next()
# OUT: [1]
next()
# OUT: [1, 2]
next()
# OUT: [1, 2, 3]
next(range(10))
# OUT: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
next()
# OUT: [1, 2, 3, 4]
next(line=[])
# OUT: [1]
next()
# OUT: [1, 2, 3, 4, 5]

Так от, щоб зрозуміти чому він так поводиться, варто знати, що змінні (і аргументи функцій) в Python це насправді не значення а посилання. А [] – конструктор порожнього списку.

В першому рядку коду створюється об’єкт функції, разом з ним створюється об’єкт списку, і стандартним значенням параметра функції призначається посилання на цей список.

Можливий варіант переписування коду так щоб він працював більш “очікувано”:

def next(line=None):
    if not line:
        line = []
    line.append(len(line) + 1)
    print line

Ну а зараз строгостатичні чистолямбдасамці можуть срати цеглою нижче. ;)


Filed under: Кодерство Tagged: помилки, робота, Python

Визначення власності

На днях у Пола Грема вийшло ще одне вельми цікаве есе на тему приватної власності та копірайтів (в контексті нещодавних спроб прийняти SOPA та PIPA). По-моєму, дуже влучна стаття і, благо, невелика – вирішив перекласти. Читаючи її я також часто згадував про оцей комікс (англ. оригінал): “Я пробував подивитись Гру Тронів і ось що вийшло” і дибілізм до якого інколи доходять всілякі правові обмеження на поширення медіа в інтернеті: у мене є підписка на Crunchyroll та думаю якось таки замутити Spotify Unlimited для онлайн музла. Так от якого дідька я мушу користуватись цим всим через американські та британські проксі відповідно, якщо я навіть гроші вже плачу. По відео це взагалі алес… Я вже не кажу, що так само не можна офіційно з України користуватись онлайн сервісами типу Hulu, BBC iPlayer, тощо.

Автор оригіналу: Пол Грем (Paul Graham)
Оригінал: Defining Property

Elephant Chained

Photo by Invisible Lens Photography/Flickr

В дитинстві я читав книжку з історіями про відомого японського суддю XVIII сторіччя, якого звали Оока Тадаске (Ooka Tadasuke). Одна зі справ, яку він судив була порушена власником ресторану. Бідний студент, що міг дозволити собі лише рис, їв його насолоджуючись запахом інших смачностей, які доносились із ресторану. І власник хотів заставити студента заплатити за запахи, які він із задоволенням нюхав. Студент же крав запах їжі!

Я часто згадую цю історію, коли чую як RIAA та MPAA звинувачують людей у крадіжці музики чи кінострічок.

Трактувати запахи як чиюсь власність звучить для нас просто смішно. Але я можу придумати ситуацію, коли можна було б брати гроші і за запах. Просто уявіть, якби ми жили на місячній базі і купували повітря по літрам. Тоді можна з легкістю уявити і підмішування запаху до цього повітря в якості небезкоштовного бонусу.

Причина, того, що право власності на запах виглядає для нас повною маячнею в тому, що на Землі на це ніхто б не повівся. Але ж цілком можливо це спрацювало б на місячній базі.

Те що вважається власністю залежить від того, що можна взагалі сприймати за власність. І останнє може не лише змінюватись з часом, а вже змінилось. Люди завжди (для деяких визначень слів “люди” та “завжди”) сприймали за власність те, що вони носили з собою. Але прадавні люди, що займались збиральництвом, наприклад, ніколи не сприймали землю як власність в тому сенсі як ми зараз. [1]

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

(Причина через яку я кажу про короткострокову жадібність полягають в тому, що люди, які керують лейблами та студіями більше розраховують на бонуси, аніж на капітал. Якби вони працювали на капітал, то шукали б шляхи як використати технології замість того, аби протистояти їм. Та створювати нове – це дуже довго. Їхні бонуси залежать від цьогорічного прибутку, а найкаращий спосіб збільшити цей прибуток – це вичавити більше грошей з того, що вони вже мають.)

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

Під “працює” я маю на увазі щось більш суттєве, аніж “коли у них просто є така можливість”. Я маю на увазі, що люди можуть брати за нього гроші тоді, коли їм не треба заставляти суспільство робити це. Тобто компанії, що продають запахи на місячній базі можуть, звісно, продовжувати продавати їх на Землі, якщо вони успішно пролобіюють закони, які заставлять нас дихати через трубки і тут (навіть якщо нам це вже не потрібно).

Божевільні заходи по захисту прав, які зараз проводять лейбли та студії, дуже нагадують подібну ситуацію. Газетам та журналам теж непереливки, але вони принаймні занепадають з гідністю. RIAA та MPAA заставили б нас дихати через трубки, якби змогли.

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

От тут дуже корисно мати працюючу демократію та багато незалежних країн. Якби у світі був єдиний авторитарний уряд, лейбли та студії купили б закони, які встановили те визначення власності, яке їм хочеться. Але на щастя є ще країни, які не є copyright-колоніями США і навіть в самих США політики все ще бояться електорату у великих кількостях. [3]

Людям, які керують у США може не подобатись, коли виборці чи інші країни відмовляються схилитись перед їхньою волею, але і ми зацікавлені в тому, аби люди, що намагають змінити закони заради власних інтересів, не мали чим нам дорікнути. Приватна власність – це дуже корисна ідея і, можливо, взагалі однин з найкращих винаходів людства. Досі кожне нове визначення приносило нам збільшення матеріального достатку [4]. Думаю, що не буде помилкою припустити, що і нове теж. Це було б трагедією, якби ми всі були змушені використовувати застарілу версію просто тому, що деякі впливові люди занадто ледачі аби оновити його.

Примітки

[1] Якщо вам цікаво дізнатись більше про збирачів, рекоменду. книжки Елізабет Машал Томас (Elizabeth Marshall Thomas): The Harmless People та The Old Way.

[2] Зміна визначення власності зазвичай спричиняється технологічним прогресом, щоправда оскільки технологічний прогрес прискорюється, цілком можливо, що і швидкість зміни визначення власності буде мінятися частіше. А це означає, що суспільству варто з граціозно пристосовуватися до цих змін, так як вони траплятимуться все частіше і частіше.

[3] Наскільки мені відомо термін “copyright-колонія” вперше використав Myles Peterson.

[4] Стан технології це не просто функція від визначення власності. Вони впливають одне на одне. І таким чином ви не можете з власної волі змінити визначення власності не зачепивши (зазвичай зашкодивши) розвиток технологій. Історія СРСР – яскравий тому приклад.

Термінологія OAuth

Тут в блозі завалялось вже більше десяти чернеток, пора потрохи розгрібати. Наступна нотатка повинна допомогти розібратись в документації по протоколу OAuth. Щоправда для того аби щось запрограмувати все одно доведеться читати документацію конкретного API.

Аутентифікація – перевірка того факту. що суб’єкт – той за кого себе видає.
Авторизація – перевірка того факту, що суб’єкт має право на доступ до певного ресурсу.
Credentials (мандат) – реєстраційна інформація потрібна для аутентифікації.

В схемі протоколу OAuth описані три агенти: клієнт (споживач, client, consumer), сервер (провайдер послуги, server, service provider) і власник ресурсу (користувач, user, resource owner).

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

Дуже часто клієнт працює від чужого імені. Наприклад браузер працює від імені користувача, використовуючи реєстраційну інформацію (зазвичай логін та пароль) яку йому довірив користувач. Клієнтом може бути веб-застосунок, який поділяється на фронт-енд та бекенд, і запити до сервера йдуть з бекенда. Але якою б не була архітектура клієнта – він все одно діє від імені користувача як одне ціле.

Захищений ресурс – це те що зберігається чи надається сервером, і потребує аутентифікації для доступу. Ресурси належать і контролюються власником ресурсу – користувачем. Будь-хто хто потребує доступу до захищених ресурсів повинен отримати дозвіл на авторизацію від власника користвача (що гарантується сервером). Ресурсом можуть бути як дані (документи, медіа, контакти) так і сервіси (публікація новин в блозі, переказ коштів і т.п).

Протокол OAuth дозволяє користувачу надати доступ клієну до захищеного ресурсу не передаючи йому свій мандат. Тобто клієнт аутентифікується як окремий клієнт і працює від свого імені з дозволу користувача.

OAuth використовує три типи облікової інформації – облікова інформація клієнта, тимчасову та токени. Специфікація називає їх відповідно consumer key and secret (client credentials), request token and secret (temporary credentials), та access token and secret (token credentials).

Перші в параметрах запиту називаються відповідно:

{
    'oauth_consumer_key': 'anonymous',
    'oauth_consumer_secret': 'anonymous'
}

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

Після того як користувач дає дозвіл, клієнту (зазвичай за допомогою GET запиту, за адресою яка повідомляється серверу параметром callback_url, хоча можливо існують і інші способи) передають тимчасовий мандат (токен та секрет запиту).

Клієнт звертається до сервера з цим токеном та секретом, і сервер замінює їх на постійні. Цей крок мені дещо незрозумілий (яку схему атаки він дозволяє уникнути?), але чомусь так воно працює.

Посилання:


Filed under: Кодерство, Павутина Tagged: API

Шизофазогенератор Маркова

Написав скрипт який на даний момент. Письменник – звертайтесь. Залишилась математика, і що я знаю дещо про керування рекламними кампаніями в Google календар з нагадуванням по SMS, бо думав, що його швидкість зміниться так: Тепер ще один сервіс не буде ніяких порад про побудову сюжету, що ортогональна проекція легко стає ізометричною після здійснення повороту на 45° до чого веду.

Можна подумати що я вже зовсім втратив здатність зрозуміло висловлюватись. Але ні. Це я вибрав досить вдалий абзац з тексту створеного скриптом, який загрібає корпус текстів з певного блогу, робить лексичний аналіз, підраховує частоту послідовностей токенів, і записує їх в базу. Далі, за цими частотами можна порахувати ймовірності з якими після даних конкретних токенів ідуть інші можливі токени. І випадковим чином з поправкою на розподіл імовірностей вибирається один з них.

Написав таку штуку, бо давно нічого не писав (в блог, а не коду), і мені хочеться вияснити можливості MongoDB. Крім того Стенфорд все відкладає свій курс NLP, а в мене на роботі в цьому напрямку вже проходять дослідження. І біля мене навіть сидить один кандитат наук.

А також мені можливо скоро доведеться здавати диплом. А його ще треба написати. Одні студенти з MIT були настільки ліниві, що замість того аби писати дипломні роботи написали програму яка пише дипломні роботи замість них. І непогано пише. Моя програмка теж непогано пише, хоча використовує набагато простішу технологію. Ось згенерований текст в не в моєму стилі:

Ні, я ж ще не знаєш? Хоча відсутність дров передбачити було неважко… Нет, с арифметикой у них, увы, атрофирована полностью. Ну як не згадати його кільця! Приблизно схожий на Юпітер – засмієте. Якщо ви колись побуваєте на ньому, то система вивалюється з грізним повідомленням “опускатись нижче по рівню” У Форті дуже мало внутрішніх перевірок на коректність роботи програми та коректність дій користувача, а я в шинку промок. Зате тепер я розумію конретику, яка в майбутньому навчитись самотужки обмінюватись інформацією між своїми копіями, схожими по роботі програмами та зовсім різними по призначенню. Також потрібно розуміти поняття реальної швидкості, тобто власне довжини вектору руху, неспроектованого.

Теорія відносності каже (якщо чесно, я сам собі так сказав; треба вчити, бо ліньки було розбирати всі варіанти, коли є бабло, то здесь ситуация совершенно иная. Эти части текста, для мене цей недолік несуттєвий =)). Завдяки окулярам ліве око бачить червоний колір однієї довжини хвилі, а не на моїх =) Угадайте, хто при читанні моїх завдань на життя згадав Вікіпедію, ТеХ, інтели, мускли, вольфрамальфа та будь-що інше, але ними користуються тільки ТеХніки ))) F# він уже присутній для користування. Давайте спробуємо уявити собі наскільки потужна обчислювальна система у загальному значенні. Більшість з них дуже маленька і закінчується об”єктами зірками і зірки знаходятся в протифазі. У Земного барицентру дві орбіти. Оскільки окремі моделі можуть зв’язуватись між собою і слідувати певній логіці, обо’єкт типу IEnumerable. Власне задля зручності роботи і було насправді, доки у нас є файлик з кодом). Рекомендую подивитись Пайтон-вставки в асемблерний код.

Вгадайте хто це міг написати?

Правда проблема з блогами які мені цікаво читати – їх текст містить багато комп’ютерного коду. А так як шизофазогенератор внаслідок вродженого порушення психіки не може генерувати хоч трохи структурований код, трапляються такі фрагменти що порівняно з ними всі попередні тексти – поезія:

————————– ;– MAIN ——- ;————————— ;– Макроси FASM-у, для мене це ще не переведено на Python3. import turtle def plotAxes(screen): turtle.reset() turtle.up() turtle.speed(0) turtle.hideturtle() turtle.down() turtle.goto(0,0) turtle.goto(0, 1) ^^^ table.[index] let crcResult = ~~~(Array.fold byteCrc 0xffffffffu (Encoding.Default.GetBytes(s))).

З чимось дівчачо-філологічним виходить набагато краще:

Ні, не чула, що вона заробила свій перший мільйон, треба самому прожити життя, отруєний грибком заздрощів. Рік тягнувся. Не люблю, але дозволь людям, що інші виросли, я не питиму. Тебе морально згвалтували настільки, що всередині”, – чистий бланк, і друге! Проте, коли такі, яких я викрила. Всяке і різне, як коханого чоловіка, інколи така правда вилазить боком. Маленькі і недосвідчені, будуємо собі вимріяний світ, не витираючи ніг. Іншими словами, графоманство. І добре, якби завтра мені витягнулись власне ті питання, які не просто знати. Його треба пропустити крізь себе, залившись алкоголем. По колу. Але я не забила на університет, сиджу вдома та плачу. Плачу, та ж. Гадаю, що надихають на добро тебе. – Чудово. – Про що і до сьогодні люди шукають добре? Зрештою, важко налаштуватись на позитив, коли одного разу, одягну школадного носа. Скажете, доля не любить солодкого?

Зразу видно що текст про почуття і про почуття і про емоції, одним словом потік свідомості. Точнісінько як оригінал…

Я б ще розказав про те яка MongoDB лапочка, розширивши тему попередньої публікації, а також про те як генерувати чистий (ну майже) корпус тексту з певного сайту за допомогою httplib2, BeautifulSoup, soupselect та регулярних виразів. Але я вже стільки награвся своїм шизофазогенератором, що боюсь в неділю через недосипання не зможу розстріляти своїх тім-лідів шариками з фарбою. А хочеться. Тому решту читайте в наступних серіях… Або самі код розбирайте.

А поки що можете почитати афоризми в стилі Канта. Теж не далекі від оригіналу. :)


Filed under: Кодерство, Павутина Tagged: математика

Початок стосунків з MongoDB

Щойно я нормально так прозрів на рахунок MongoDB і того чому в мене від неї відпадали курсори, а запити були тугими. І йомайо яка це чудова база даних! Вона настільки приємніша за реляційні, наскільки мови з динамічною типізацією приємніші за мови зі статичною. :-P І як Python – спочатку неймовірно проста, але чим довше знаймишся – тим більш глибокі можливості відкриваються.

Задача яку я розв’язував – підрахунок частоти послідовних трійок токенів в тексті, де токен – слово, пунктуація, або невидимі символи (переноси рядків, прогалики, табуляції). Вже при 20000 трійок кожен запис в базу займав 200 мілісекунд. Це від того, що перед тим як додати одиничку до кількості трійок певного виду потрібно їх в базі даних знайти. Але так як токенами може бути пунктуація, більшість трійок, це “після слова йде кома, після коми прогалик”. Зрозуміло що після кожної коми повинен йти прогалик. А після коми з прогаликом з майже однаковою ймовірністю може йти купа різних слів. Тому трійок для того аби згенерувати текст статистично схожий на текст певного корпусу – мало.

І я вирішив перейти до масиву. Тобто записи в базі даних будуть виглядати як словник з трьох слів та кількості вживань, а словник з списку трьох слів, слова яке йде за ними та їх кількості вживань. Але індекс по списку не дуже то допоміг. А все виявилось тому, що індекс по масиву дозволяє навіть перевіряти входження елемента в список. Чи входження всіх елементів списку в список. Зрозуміло що розмір індексу, зростає так немало (тому напевне на розмір ключа встановлено обмеження не більше 800 байт), та й витрати часу на запити теж. Тому краще повернутись назад до індексу по окремих скалярних полях документа. І всьо повинно бути чотко!

А про те що з того вийшло – трохи пізніше.

Література:


Filed under: Інструменти, Кодерство Tagged: NoSQL