-
Замечательный движок Эгея
Этот блог работает на движке Эгея. Я узнал о нем из блога Ильи Бирмана (автора проекта). Поначалу мое отношение было скептическим — мало ли сейчас различных движков? Решив вести собственный блог, я перебрал несколько движков и КМС, и вышло так, что только Эгея не только удовлетворила все мои требования, но и приятно удивила в дальнейшем.
Почему я не использовал Друпал? Его долго собирать. Это не готовая КМС, а конструктор. Установив Друпал, приходится еще полдня ставить модули и лазить в настройках. Эгея же просто работает. В ней нет хлама вроде опросов, древовидных тегов, визуального редактора, архива за прошлые года. Она минималистична и быстра.
Эгея позволяет сконцентрироваться на содержимом блога, а не его техническом устройстве.
Пока что я вижу в движке два недостатка: вики-разметка и кодировка cp1251.
Использование разметки вместо обычного ХТМЛ является правильным решением: набирать теги руками замучаешься, а визуальные редакторы выдают отвратительный код. Вот только Илья не угадал с разметкой, лучше было бы взять не вики, а маркдаун, он проще и удобнее. Впрочем, к вики быстро привыкаешь.
Кодировка cp1251 устарела и отовсюду вытесняется УТФ, так как не позволяет использовать символы юникода и не дружит со многими языками. Эгею нужно перевести на УТФ обязательно, cp1251 — преграда на пути проекта к широкой аудитории.
И тем не менее, Эгея — лучший движок для блога из всех, что мне приходилось видеть. Помимо очевидных плюсов, вроде быстрой установки и высокой скорости работы, в ней есть сюрпризы. Например, картинки вставляются перетаскиванием файла в браузер. Это этого получаешь дикий, нестовый восторг! Не нужно больше искать изображения в дурацком диалоге выбора файла!
Эгея легко поддается темизации, написать свою тему для нее нетрудно. Движок поддерживает пользовательские блоки — это ПХП-файлики, содержимое которых выводится в определенное место, например, перед статьей, после статьи, в сайдбаре, в подвале и т.д. Мне понадобилось всего три таких файла — сайдбар с меню, область после статьи для социальных кнопок и подвал для джаваскрипта (метрика, подствека кода).
Словом, нисколько не ошибся с выбором Эгеи. Отличный движок, желаю Илье не забрасывать и развивать прект.
-
Мысли о Друпале
Друпал (анг. Drupal) — система управления содержимым, написанная на ПХП Дрисом Бёйтартом. Вместе с Вордпрессом и Джумлой входит в большую тройку КМС.
Историю Друпала вы можете прочесть в Википедии. Ознакомиться с текущим состоянием дел можно на официальном сайте. Начинающим будет полезно зарегистрироваться на форуме Дупал.ру, сообщество активно, есть подборка обучающих статей.
В этом посте я хочу выразить некоторые мысли, которые сформировались за долгое время работы с Друпалом. Это отдельные тезисы с краткими пояснениями.
Гибкость системы. Главным достоинством Дупала является его гибкость. Не секрет, что любая КМС в той или иной степени ограничивает разработчика. Дрис и команда разработали систему модулей и хуков. Она позволяет менять поведение Друпала без правок ядра.
Хуки — именованные функции. За хакерским словечком «хук» скрывается банальная вещь — функция, имя которой удовлетворяет шаблону
<имя модуля>_<имя хука>
. Эти функции должны располагаться в теле модуля. Друпал опрашивает модули на предмет наличия этих функций и вызывает их. При этом функция-хук должна либо вернуть какие-то данные, либо изменить те, что были переданы ей по ссылке. Хуков много, вызываются они в разное время. Некоторые модули могут определять собственные хуки.Множество модулей. Система модулей и хуков понравилась разработчикам. В настоящее время число всех модулей оценивается в несколько тысяч. В актуальном состоянии поддерживается около тысячи модулей. Написать свой модуль легко — это ПХП-файл с расширением
*.module
с функциями-хуками внутри. Описание каждого хука с примерами смотрите в документации.Не все в Друпале так идеально, как кажется. Друпал имеет солидный возраст, это зрелый программный продукт. Однако, некоторые его компоненты устарели и нуждаются в переработке. Например, работа с формами. В любом современном фреймворке форма, поля и валидаторы — это классы. Нужно расширить форму — наследуете от нее свой класс. Работа с классами проще, чем с хэш-массивами двойной вложенности. Друпал хранит переводы и кэш в базе, что отрицательно сказывается на производительности. Система нод (или сущностей) Друпала раскидывает поля по отдельным таблицам, вместо того, чтобы добавлять поля к имеющимся.
Не делайте из Друпала культ. Начинающим веб-разработчикам кажется, что Друпал способен на все. Это правда, но лишь в теории. Легкость создания больших сайтов без написания кода компенсируется многими уровнями абстракций и чрезмерно сложной логикой. Приступая к новому проекту, спросите себя, так ли нужен здесь Друпал, нельзя ли обойтись чем-либо попроще? Например, вы решили вести блог. Стоит ли качать Друпал, ставить на него и настраивать кучу модулей, если проще взять специализированный движок?
Любите Друпал не больше других средств разработки. Не зацикливайтесь на Друпале. Постарайтесь освоить несколько технологий, языков, фреймворков, КМС. С разнообразием приходит опыт. Заимствуйте удачные решения из одного проекта в другой. Старайтесь не привязывать удачные решения только к Друпалу. Например, если в модуле есть код рассылки смс, оформите его в отдельном файле и выложите на Гитхаб.
Комментарии из старого блога
08/19/12 jedi: Согласен со всем, жалко мало написали. Сам перехожу на yii
-
Победителя определяет скорость
Скорость разработки — это:
- один из основных критериев, определяющих профессионализм разработчка;
- главный аргумент в выборе тех или иных средств;
- решающий фактор в бизнесе как для стартапа, так и для транснационального гиганта.
Все три тезиса могут быть оспорены в непринужденной дискуссии, но утверждают себя на производстве — всё всем нужно вчера. В таких условиях программисту следует внимательнее отнестить к методологии и средствам разработки.
Для рутинных действий и автоматизации процессов хорошо подходит Питон — скриптовый язык с динамической типизацией. Он поддерживает множество парадигм, позволяет писать код так, как нужно именно вам. Например, если скрипт простой, вы сразу описываете рабочую логику, а не мусор вроде
public class Foo
иpublic static void main()
.С Питоном вы становитесь эффективнее. Работа с почтой, разбор и формирование XML, смс-рассылки, перегон данных из одного формата в другой, обработка офисных документов, чтение и запись DBF, COM-автоматизация, взаимодействие с сервисам Гугла, быстрые сайты на Джанго, работа с устройствами по серийному порту и уйма всего другого — это Питон. Плюс кросплатформенность, малый размер дистрибутива, пакетный менеджер (даже два — pip и pypm), масса библиотек на все случаи жизни. Плюс скорость.
Не бойтесь делегировать больше задач сторонним утилитам. Например, вы программируете сайт, и в какой-то момент требуется ужать и обрезать загруженное пользователем изображение. Или сгенерировать капчу. Или штрихкод. Или QR-код. Или Excel-книгу. Или отправить письмо. Стандартный подход — подключить модуль, просмотреть примеры, написать код. Вы потратили время, код увеличился.
Быстрый подход — задействовать консольную утилиту. Работа с изображениями — ImageMagick, генерация капчи — он же, отправка письма — sendmail или blat для Винды, работа с Excel — скрипт на VB Script, штрихкод — GNU Barcode, QR-код — Google Charts. И так далее.
Да, есть в этом подходе и минусы — проект становится зависим от стороннего ПО, использование утилит порождает внешние процессы, что значительно медленнее, чем вызов функций.
Однако, вы выигрываете в скорости разработки. Вы представите публике рабочую версию продукта быстрее, чем ваш конкурент — коллега или стартап. И у вас будет время на то, чтобы подключить нужные классы и заменить утилиты нативными API, в отличии от тех, чей прект вообще не вышел из тестирования.
Не бойтесь внедрять новые технологии. Роман Ворушин внедрил Джанго-систему в банке, где все было написано на Джаве. Иван Сагалаев принес Джанго в Яндекс. Я, не являясь специалистом такого уровня, внедрил Питон и Джанго в организации, где был только PHP и сервера на Винде.
Скорость очень убедительна.
-
Умирает ли РСС?
В последнее время в Сети то и дело пишут о том, что формат РСС умирает. Дескать, все продвинутые читают Твиттер и Гугл+, все актуальное и интересное там, а РСС для неудачников.
Поговорим об этом.
Чтобы развеять миф, озвученный в первом предложении, необходимо и достаточно ответить на два вопроса:
- Какие преимущества есть у РСС-лент?
- Что произойдет, если формат действительно умрет, и все сайты мира отключат РСС?
Преимущества
Во-первых, РСС — очень простой формат, обычная XML-ка.
Взгляните на официальный документ — структура совершенно прозрачна. Причем не обязательно соблюдать условности вроде тега
<title>
— современные приложения в состоянии разобрать даже самые невалидные ленты. Например, сайт slon.ru отдает ленту только с тегами<description>
,<link>
и<pubDate>
, что никак не мешает ее чтению.Во-вторых — открытость и минималистичность формата делает работу с ним очень удобной. Построение и парсинг XML — обычная рутинная задача веб-разработчика. Собрал XML и сохранил на диск — приложение пользователя само его заберет и распарсит. Никаких OAuth-танцев, токенов и авторизаций.
Третий пункт — практически каждый сайтовый движок, CMS, форум может генерировать РСС. Во многих движках есть ленты по отдельным авторам, тегам, комментариям к статьям, разделам форумов и даже поисковым запросам! Это же очень удобно — подписались на двух интересных авторов и читаете только их. Или отслеживаете комментации в интересной статье.
Четвертый — существет немыслимое количество приложений для чтения лент, для всех операционных систем и платформ. Читать можно в браузере, в десктоп-приложениях, в телефонах, планшетах. Немало сервисов основано на передачи данных из одного источника в другой именно в РСС-формате. Кросспост в Твиттер, Фейсбук и другие социальные сети основан на РСС-лентах. Сервис twitterfeed — абсолютный монополист в этой области — обслуживает на текущий момент свыше шести миллионов лент!
Пятый — в некоторые сайты помещают в ленту статьи целиком, а не только анонс. Если при этом в статье сохранены все теги, картинки и форматирование, то РСС-читалка становится полноценным браузером. Не нужно открывать сайт, загружать рекламу и баннеры.
Шестой — продвинутую читалку вроде Google Reader можно использовать как каталог избранных ссылок. На многих сайтах есть возможность помечать статью как избранную или добавлять в закладки (что по сути одно и то же). При этом они хранятся разрозненно: на Хабре — избранное только Хабра и т.д. Однако, если отмечать статьи в едином пространстве (в РСС-читалке), то поиск и просмотр избранных статей станет намного проще.
Представим, что РСС умер
Как теперь распростронять информацию с сайта, блога? Через Твиттер. Для того, чтобы организовать кросспост, владельцу сайта необходимо выполнить следующие шаги:
- зарегистрировать в Твиттере новое приложение;
- найти модуль для своей CMS или библиотеку для языка/платформы;
- все настроить, запустить, протестировать.
Хорошо, если сайт работает на какой-нибудь CMS вроде Дупала, Вордпресса или Джумлы. Для них модули уже есть. А как быть владельцам малораспространенных CMS или тем, чьи сайты работают на фреймворках или самописных движках? Уверены, что сможете все организовать сами? Действительно ли это проще, чем добавить ленту в twitterfeed?
Далее, при кросспосте нужно сокращать ссылки. Кто будет этим заниматься? Теперь ответственность лежит на вас. Регистрируемся в [Bit.ly]((http://Bit.ly), получаем открытый и закрытый ключи, качаем библиотеку для нужного языка, проходим OAuth-авторизацию и //только теперь// можем приступить к сокращению ссылок! Аналогично с Goo.gl: сперва включаем сервис в консоли API, получаем ключи, качаем библиотеки, читаем доки, авторизуемся и сокращаем. Уверяю, не все так просто. Тонкости работы с goo.gl я подробно описывал на Хабре.
Исходя из вышесказанного, можно с уверенностью предсказать возникновение сервисов, которые возьмут волокиту на себя. От нас только потребуется передавать информацию в удобном виде — вот заголовок, вот тело статьи, вот ссылка на оригинал. Формат, вероятно, XML — он лучше подходит для структурированных данных. И к чему мы пришли? Не к тому ли, что имеем — РСС и twitterfeed?
Не забываем, что размер твита ограничен 140 символами. Из них половина может уйти на заголовк статьи, плюс ссылка, плюс хэштеги и всё — упираемся в лимит. В итоге, полезность статьи можно оценить исключительно по заголовку, что, согласитесь, очень неудобно в сравнении с РСС.
И последний довод. Всю информацию, поступающую в Твиттер, можно разделить на два типа. Первый тип — то, что написано живыми людьми, неважно, при помощи какого приложения. Написал ли человек твит прямо на сайте, или отправил с телефона, или с Инстаграма — это первый тип. Такая информация отражает актуальные действия и мысли человека, т.е. прямо отвечает на вопрос-слоган «Что ты делаешь сейчас»?
Информация второго типа — та, что публикуется ботами и сервисами. В основном, это кросспост из блогов, новостных сайтов и сообществ вроде Хабра. Такая информация слабо привязана ко времени и имеет большую актуальность. Например, так ли важно, когда вы прочитаете новую техническую статью — спустя 10 минут, час или день после ее публикации?
Твиттер очень хорош для распространения актуальной информации первого типа. А со вторым типом он обращается плохо — информация тонет в сплошном потоке. Если ваш твит с ссылкой на статью не прочли в постоянно обновляемой ленте сейчас, то уже не прочтут никогда.
Твиттер не убил РСС-ленты, просто вытеснил их оттуда, где требуется скорость и актуальность. В остальном, РСС отлично справляются с задачей, заменить их нечем и не требуется.
Комментарии из старого блога
05/21/13 sheber: Отличный пост, спасибо. Кстати, Google Reader закрывается http://googlereader.blogspot.com/2013/03/powering-down-google-reader.html
-
Работаем с Твиттером
Как по-быстому связать приложение на Питоне с Твиттером?
Ответ — подключить библиотеку oauthtwitter.
Почему не python-twitter? Потому что первая гораздо меньше по объему кода и числу зависимостей от дополнительных модулей: 300 строк кода против 4000!
Установим необходимые библиотеки:
pip install ouath2 pip install httplib2 pip install simplejson
Для работы с Твиттером нужно зарегистрировать приложение. Твиттер позволяет указывать ссылки вида
localhost
или127.0.0.1
в поле «Callback URL», что очень полезно при разработке на локальной машине.Consumer key — это открытый ключ приложения, что-то вроде логина. Consumer secret — закрытый ключ, которым подписываются запросы к Твиттеру. Если вы где-то опубликовали его, немедленно смените в настройках приложения.
Авторизация в Твиттере проходит в несколько шагов.
Шаг 1: запрос на авторизацию
import oauthtwitter CONSUMER_KEY = "key" SECRET_KEY = "secret" # Инициализация клиента по ключам def sign_init(request): client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY) # Уникальный токен, действительный только для одной авторизации request_token = client.getRequestToken() # Сохраняем токен в сессию пользователя. Можно сохранить на диск или в БД request.session["request_token"] = request_token # Получаем уникальный адрес авторизации на основе токена url = client.getAuthorizationURL(request_token) # Перенаправляем пользователя на страницу ввода пароля return redirect(url)
Шаг 2: ввод логина и пароля на стороне Твиттера
Шаг 3: возврат пользователя на ваш сайт
После авторизации пользователь будет направлен обратно на ваш сайт. Напомню, что в приложении на стадии тестирования у нас указано что-то вроде
http://localhost:8080/twitter/callback
По этому адресу должен быть обработчик, который завершит процесс авторизации.def sign_callback(request): # Извлекаем сохраненный ранее в сессии токен. # Если токена нет, то пусть начинает всё с начала. request_token = request.session.get("request_token") if not request_token: add_message(request, ERROR, u"Request token not found.") return redirect(frontpage) # Ключ валидации запроса из командной строки. oauth_verifier = request.GET.get("oauth_verifier") if not oauth_verifier: add_message(request, ERROR, u"OAuth verifier not found.") return redirect(frontpage) # Снова инициализируем клиента client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY) # Извлечени параметров доступа access_token = client.getAccessToken(request_token, oauth_verifier) print access_token >>> { 'oauth_token_secret': 'xTbNbG0IcUGgng9pyNdy******************', 'user_id': '123123123', 'oauth_token': '78741204-cLgfThwKXuqudeXGTQP***********************', 'screen_name': 'username' }
Отлично! Как видно, access_token представляет из себя словарь со всеми нужными данными: идентификатором и именем пользователя, открытым и закрытым ключами доступа.
Дальнейший сценарий зависит от архитектуры вашего приложения. Например, на основании screen_name заводится новый пользователь (или извлекается имеющийся). Оба ключа записываются в профиль пользователя. Теперь можно работать с Твиттером:
# Инициализация клиента с ключами приложения и пользователя client = oauthtwitter.OAuthApi(CONSUMER_KEY, SECRET_KEY, user_oauth_token, user_oauth_token_secret) # Извлечение твитов пользователя timeline = client.GetUserTimeline() # Твитнуть сообщение client.UpdateStatus("Python testing") # Получить фолловеров timeline = client.GetFollowers()
И так далее, список всех методов ищите в коде класса. Очень доволен этой библиотекой, использую ее в двух проектах.
Комментарии из старого блога
02/11/13 Майя Любимая: я ничего не понимаю
02/20/13 Иван Гришаев: То же самое могу сказать о вашем комментарии.
-
Создание файлов Excel
В статье «Почему форматы Microsoft Office такие сложные?» Джоэл Спольски пишет:
Заставьте Office делать грязную работу за вас. Word и Excel завязаны на сложных объектных моделях, основанных на автоматизации COM, что позволяет программно делать всё, что угодно. Во многих ситуациях проще будет использовать код Office, чем пытаться реализовать его с нуля.
Действительно, если требуется сформировать сложный офисный документ, проще сделать это вызовами API через COM-соединение. Однако, для создания простой эксель-таблички можно задействовать библиотеку xlwt.
Библиотека ставиться просто:
pip install xlwt
Требуется сформировать таблицу с тремя колонками:
- номер лицевого счета абонента, строковый тип;
- дата показания, тип дата;
- показание, тип число.
Проект выполнен на Джанго. Есть модель показания, переданного абонентом:
class Statement(models.Model): user = models.ForeignKey(User) value = models.DecimalField(max_digits=12, decimal_places=6) date = models.DateTimeField(default=datetime.now)
Показания, которые необходимо записать в таблицу, извлекаются следующим образом
statements = Statement.objects.filter(date__range=(t1, t2))
Формирование файла Excel будет выглядеть так:
import xlwt # Определяем формат ячеек для дат date_style = xlwt.XFStyle() date_style.num_format_str = "M/D/YY" # Определяем формат ячеек для чисел num_style = xlwt.XFStyle() num_style.num_format_str = "0.00" wbk = xlwt.Workbook() # Новая книга sheet = wbk.add_sheet("statements") # Новый лист в книге # Добавляем шапку таблицы sheet.write(0, 0, u"Лицевой счет") sheet.write(0, 1, u"Дата") sheet.write(0, 2, u"Показание") # Обход показаний, statements — объект QuerySet из Джанго for i, s in enumerate(statements): # i — индекс итерации, используется как номер строки sheet.write(i+1, 0, s.user.username) sheet.write(i+1, 1, s.date, date_style) sheet.write(i+1, 2, s.value, num_style) # Задаем ширину колонок sheet.col(0).width = 5000 sheet.col(1).width = 5000 sheet.col(2).width = 5000 # Запись файла wbk.save("path/to/file.xls")
-
Запись непойманных исключений в файл
На работе у меня много скриптов, написанных на питоне, и большая часть из них выполняется ночью. Проблема — любой, даже самый надежный скрипт может упасть. Не удалось соединиться с БД, не найден нужный файл, отвалился сетевой ресурс, прислали кривой реестр.
Обрабатывать исключения на каждой операции — утомительно, код распухает на глазах. Гораздо важнее не отлавливать каждую ошибку, а фиксировать факт ее появления и ситуацию, в которой она возникла.
Модуль cgitb устанавливает свой обработчик на всплывающее исключение. Он пишет в файл всю необходимую информацию: дату, время, исключение, его параметры, имя скрипта, фрагмент кода, где было возбуждено исключение и локальные переменные.
Имея эти данные, нетрудно выявить причину ошибки и внести в скрипт нужные коррективы. Модуль очень полезен для CGI-скриптов: ошибки не придется искать в логах Апача, тем более, что такой подробной информации вы там не найдете.
Подключить обработчик очень легко:
import os import cgitb cgitb.enable(display=False, logdir=os.path.dirname(__file__))
logdir — директория, куда будет записан html-файл с информацией об ошибке. В данном примере указана директория, в которой расположен исполняемый скрипт. В CGI-скриптах должна быть указана директория, к которой нет публичного доступа.
При работе с cgitb важно подключать его как можно быстрее, желательно, в начале скрипта. Это поможет обработать ошибки импорта библиотек.
-
Работа с файлами mailbox
Чем хорош почтовый клиент Mozilla Thunderbird?
Хотя бы тем, что хранит письма в удобном формате mailbox. Благодрая этому можно рулить почтой программно: считывать содержимое ящика, удалять и добавлять письма.
Зачем это может понадобитсья? Например, каждый день вам на почту приходят реестры платежей, которые нужно выгрузить из аттача, распаковать, и, в зависимости от имени файла, скопировать в определенную директорию. Напрашивается автоматизация процесса.
В составе богатой библиотеки Питона есть модуль mailbox. Небольшой пример:
import os import cgitb cgitb.enable(display=False, logdir=os.path.dirname(__file__)) import mailbox MAILBOX_PATH = "path/to/mailbox.file" # Путь к файлу ящика DATA_PATH = "store/path" # Директория для файлов mbox = mailbox.mbox(MAILBOX_PATH, create=False) for i, message in enumerate(mbox): attachments = message.get_payload() for attachment in attachments: filename = attachment.get_filename() if filename and filename.endswith(".txt"): body = attachment.get_payload(decode=True) filepath = os.path.join(DATA_PATH, filename) with open(filepath, "w") as f: f.write(body) mbox.remove(i) mbox.close()
Основной цикл обходит все письма в ящике. Переменная attachments — это список частей письма. Частью может быть всё — простой текст, HTML-сообщение, файловое вложение и т.д.
get_filename()
возвращает имя части. Для файлов оно будет отлично от None. Нас интересуют только текстовые файлы. Тело файла извлекается методомget_payload()
части.При передаче файла он может быть закодирован методами base64 или uuencode. Чтобы получить исходный файл, передается параметр
decode=True
. Полученный файл пишется на диск.Сообщение удаляется из ящика. По окончании цикла ящик закрывается.
-
Рассылка смс в Питоне
Отправлять короткие сообщения можно с помощью любого из многочисленных сервисов смс-рассылок.
Я остановил свой выбор на LittleSMS. Низкая фиксированная цена, удобные API, подробная документация, готовые решения для многих языков и платформ.
Работа с сервисом осуществляется по протоколу HTTP GET-запросами. При регистрации вы получите API-ключ. Этим ключом подписываются все запросы. Ключ не является паролем к учетной записи. Если ключ где-то засветился, немедленно смените его в личном кабинете сервиса.
Для Питона рекомендую использовать мою библиотеку с Гитхаба.
Пример работы:
import littlesms # Инициализация класса api = littlesms.Api("user", "API_key") # Проверка баланса. print api.balance() >>> {u'status': u'success', u'balance': 0.5} # Отправка сообщения. print api.send(u"Hello, World!", "7xxxxxxxxxx") >>> { u'count': 1, u'status': u'success', u'recipients': [u'7xxxxxxxxxx'], u'price': 0.5, u'parts': 1, u'test': 0, u'balance': 0.5, u'messages_id': [u'xxxxxx'] } # Отправка сообщения нескольким адресатам с подменой поля «отправитель». recipients = ("7xxxxxxxxx1", "7xxxxxxxxx2", "7xxxxxxxxx3") print api.send(u"Hello, World!", recipients, sender="Anonym") >>> { u'count': 1, u'status': u'success', u'recipients': [u'7xxxxxxxxx1', u'7xxxxxxxxx2', u'7xxxxxxxxx3'], u'price': 0.5, u'parts': 1, u'test': 0, u'balance': 0.5, u'messages_id': [u'xxxxxx1', u'xxxxxx2', u'xxxxxx3'] } # Если компьютер расположен за прокси со сложной схемой авторизации. PROXY = { "proxy": "172.27.86.8", "port": 3128, "user": "ivan", "passw": "secret" } opener = littlesms.curl_opener(**PROXY) api = littlesms.Api("user", "API_key", opener=opener) # Пример работы в облачной платформе App Engine. opener = littlesms.gae_opener() api = littlesms.Api("user", "API_key", opener=opener) # Пример обработки исключения. try: print api.send(u"Hello, World!", "7xxxxxxxxxx", sender="TooLongSender!!!111") except littlesms.ApiError, e: print e >>> Error 7: incorrect sender
Библиотека активно используется больше года в проекте личного кабинета Читинской энергосбытовой компании. На текущий момент отправлено около 15000 сообщений.