Вторая часть сравнения python и tcl

Автор: admin от 4-02-2018, 16:50, посмотрело: 179

В предыдущей статье была описана реализация задачи сбора данных о звонках с АТС, включающее в себя получение, разбор данных и добавление в БД. Решение данной задачи представлено на двух языках программирования — python и tcl. И вот, как и обещал, представляю код (на двух языках) WEB-интерфейса, включающего в себя телефонный справочник и отчеты о звонках.

localhost/?query_type=external». query_type может принимать значения: internal — справочник внутренних телефонов, external — список внешних линий, report — отчет по звонкам, ldap — справочник из АД.



def application(environ, start_response):
    status = '200 OK'
    #  проверяем наличие параметров в запросе и всяко-разно реагируем
    if environ['QUERY_STRING'] == '':
        output = bytes((header() + body() + footer()).encode('utf8'))
    elif environ['QUERY_STRING'].split('&'):
        paramDict = {item.split('=')[0]: item.split('=')[1] for item in environ['QUERY_STRING'].split('&')}
        if paramDict.get('query_type') == 'internal':
            output = bytes((header() + body() + getInternalNumbers() + footer()).encode('utf8'))
        elif paramDict.get('query_type') == 'external':
            output = bytes((header() + body() + getCOline() + footer()).encode('utf8'))
        elif paramDict.get('query_type') == 'report':
            output = bytes((header() + body() + ReportForm() + ReportData(environ) + footer()).encode('utf8'))
        elif paramDict.get('query_type') == 'ldap':
            domain = paramDict.get('domain')
            group =  paramDict.get('group')
            output = bytes((header() + body() + getLDAPusers(domain, group) + footer()).encode('utf8'))
        else:
            output = bytes((header() + body() + footer()).encode('utf8'))
    response_headers = [('Content-type', 'text/html;charset=utf-8'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]


В обоих случаях значения параметров берутся из массива переменных: в питоне это environ['QUERY_STRING'] в тикле rivet::var.



proc main {} {
    if { [::rivet::var exists query_type] } {
        set query_type [::rivet::var get query_type]
        if {$query_type == "internal"} {
            set output "[header] [body] [getInternalNumbers] [footer]"
        } elseif {$query_type == "external"} {
            set output "[header] [body] [getCOline] [footer]"
        } elseif {$query_type == "ldap"} {
            set output "[header] [body] [getLDAPusers] [footer]"
        } elseif {$query_type == "report"} {
            set output "[header] [body] [reportForm] [reportData] [footer]"
        }
    } else {
        set output "[header] [body] [footer]"
    }
    return $output
}


Т.е. чтобы было более понятно:



set output "[header] [body] [reportForm] [reportData] [footer]"


это означает, что значение переменной $output будет включать в себя результат выполнения процедур: header, body, reportForm, reportData и footer.



header — возвращает заголовок страницы. css используется один и тотже, выглядит всё одинаково.





Начальная страница:



Вторая часть сравнения python и tcl



footer — процедура вывода «низа» страницы





Основное «тело» страницы
def body():
 
<spoiler title="Python + Tcl">
   txtBody = '<table><tr><td><h2 align=left>ТЕЛЕФОНЫ</h2></td></tr>n' 
               '<tr><td>{}</td></tr></table>n'.format(menu())
    return txtBody


proc body {} {
    set txtBody "<table><tr><td><h2 align=left>ТЕЛЕФОНЫ</h2></td></tr>n
    <tr><td>[menu]</td></tr></table>n"
    return $txtBody
}


menu — вывод меню:





 Tcl


Теперь посмотрим как выглядит справочник внутренних номеров (он же телефонный справочник) снаружи:



Вторая часть сравнения python и tcl



и внутри, за это (в части касающейся вывод списка номеров) отвечает процедура getInternalNumbers:





 Tcl


Для работы с СУБД для питона был взят pymysql, для тикля mysqltcl. Что там, что там соединение с БД пишется в одну строку:



def connectDB():
    c = pymysql.connect(
        db='ats',
        user='ats',
        passwd='pass',
        host='x.x.x.x',
        charset='utf8')
    return c


proc connectDB {} {
    return [mysql::connect -host localhost -user root -db ats]
}


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



Вторая часть сравнения python и tcl



Отчет разбит на две процедуры — это вывод формы и запрос и вывод полученных данных.

Форма ничего особенного не представляет, генерится процедуркой ReportForm:





 Tcl


В процедуру ReportData включена проверка корректности ввода параметров (номер и дата), т.е. своего рода защита от SQL-иньекций и невнимательности пользователей, запрос к БД и вывод данных на экран. Конечно, это можно было разбить еще мельче но я не стал.





 Tcl


Тут есть некоторые различия в алгоритме преобразования даты. Так как в mysql дата (в моём случае) хранится ввиде YYYY-MM-DD, а для нас этот формат неудобен, то и была введена конвертация даты из одного формата в другой.



Для питона использовались встроенные функции:



date_begin = time.strftime("%Y-%m-%d", time.strptime(str(paramDict.get('date_begin')), "%d.%m.%Y"))


Но для tcl я поступил по другому. Ввиду того, что проверка на правильность ввода даты производится regexp-ом:



if { [regexp -nocase -- {^(0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.](19|20[0-9][0-9])$} [::rivet::var get date_begin] match d m y]}


То на выходе этой команды, дата уже разбита на составные части и её надо просто скомпоновать так как требуется:



set dBegin "$y-$m-$d"


И еще в реализации на tcl строку:



rowData = '<td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>'
        .format(row[0], row[1], row[2], row[3], row[4], row[5], row[5], row[7], row[9], row[9], row[10])


заменил циклом:



for {set i 0} {$i <=10} {incr i} {
    append rowData "<td>[lindex $row $i]</td>"
}


Вот и всё.



Напоследок, хоть процедура получения данных по LDAP и выходит за рамки темы статьи но входит в проект, то будет справедливым показать и её:





Все файлы доступны на BitBucket. На этом повествование на тему сравнения python и tcl прекращаю, во всяком случае пока не набёрется материал.

Источник: Хабрахабр

Категория: Программирование » Game Development

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *