Желание изучить питон было давно. Я много где слышал что он хорошо подходит для прототипов, скриптов и небольших приложений. Он отличается высокой скоростью разработки и низким порогом вхождения. Динамичность — непривычно, но решаемо.
И вот, написал первый скрипт. Он оптимизирует перемещение на «сегодня» просроченных задач в тудуисте. Перенос в приложении выполняется в 3 действия: выделить задачи с зажатым шифтом, пройти через пункты меню и нажать заветную кнопку: «перенести на сегодня». Это не всегда получается с одной попытки. Время для автоматизации!
Установка Python 3
Не нашел причин, чтобы начать знакомство не с 3 версией питона. И, так как в Mac OS X El Capitan, установлена версия 2.7, то рассмотрим простой способ установки Python 3.
Понадобится менеджер пакетов Homebrew. У кого нет — советую. Для его установки введем в терминале:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Теперь установим третий питон:
brew install python3
Проверить работоспособность можно набрав в консоли python3
.
Получение пакета для работы с тудуистом
Следующий этап — установка библиотеки для работы с АПИ тудуиста. Воспользуемся менеджером пакетов pip3, который поставляется вместе с Python 3:
pip3 install todoist-python
Напоминаю о командной оболочке Zsh, о которой я писал ранее. Подключив плагины brew
и pip
можно добавить автодополнение для команд и пакетов.
Среда разработки
Автодополнение, рефакторинг, отладка — все это помогает на любых стадиях изучения языка. Поэтому я воспользовался IDE от JetBrains — PyCharm CE. Это бесплатная версия, в которой есть все необходимое.
Стиль кода и именования
Планирутся отдельная статья. А пока — о стиле именования.
Имена функций, методов и переменных экземпляров классов должны состоять из маленьких букв, а слова разделяться символами подчеркивания:
def foo_bar(new_value):
Стиль mixedCase допускается в тех местах, где уже преобладает такой стиль, для сохранения обратной совместимости:
def fooBar(newValue):
Для атрибутов и непубличных методов используется один символ подчёркивания перед именем:
_private_value = 3
Итерация и получение значений из коллекций
Библиотека todoist возвращает на запрос о просроченных задачах словарь или список. Возник вопрос: как работать с коллекциями?
Итерация оказалась похожа на foreach
из C#:
for overdue_item in overdue_items:
item = api.items.get_by_id(overdue_item['id'])
print item
Для получения значения словаря есть 2 способа . Первый — обращение по ключу:
id = overdue_item['id']
Но, если значения нет, возникнет ошибка — KeyError: 'id'
. Поэтому при неуверенности, используйте get
:
id = overdue_item.get('id')
Если значение отсутствует, метод вернет значение по умолчанию — None
.
Преобразование и работа с датой
Рассмотрим как парсить дату, находить дельту, добавлять значения и приводить к определенному строковому формату.
Разберем построчно код из моего скрипта:
item_due_date = datetime.strptime(item['due_date_utc'], '%a %d %b %Y %H:%M:%S %z')
delta = datetime.now(timezone.utc).date() - item_due_date.date()
item_today_date = item_due_date + timedelta(days=delta.days)
item.update(due_date_utc=item_today_date.strftime('%Y-%m-%dT%H:%M:%S'))
- По ключу
due_date_utc
получаем дату в формате"Fri 26 Sep 2014 08:25:05 +0000"
. Выражением%a %d %b %Y %H:%M:%S %z
переводим в понятный питону формат. Документация по значениям переменных из выражения. - Находим разницу между текущей датой и датой полученного объекта.
- Актуализируем дату объекта, добавляя к нему полученную разницу дней.
- Переведем дату в строку используя
%Y-%m-%dT%H:%M:%S
и отправим изменения в тудуист.
Типы выполнения модуля с кодом
Часто, читая код на гитхабе, встречал конструкцию:
if __name__ == "__main__":
...
Выясним ее предназначение.
Когда исполняется файл с кодом, выполняются все команды на нулевом уровне: задаются специальные переменные, импортируются модули, определяются функции и классы. Одна из специальных переменных — __name__
. Она хранит имя модуля, который вызвал скрипт.
Например, модуль вызвали из файла foo.py
:
import TodoistOverdue
Переменная __name__
примет значение foo
. Если вызвать скрипт напрямую из терминала:
python TodoistOverdue.py
__name__
инициализируется значением __main__
. И тогда выполнится весть код из условия if __name__ == "__main__":
. Получается, модуль может работать и библиотекой и независимым приложением.
Добавление атрибутов командной строки
Мой скрипт может принимать значение токена АПИ тудуиста. Для этого скрипт вызывается с параметром -t
:
python TodoistOverdue.py -t 0123456789abcdef0123456789abcdef01234567
Рассмотрим построчно, как задавать описание скрипта и определять аргументы:
parser = argparse.ArgumentParser(description="Moving overdue tasks for today in todoist")
parser.add_argument("-t", "--token", help="Todoist API token")
args = parser.parse_args()
- Инициализируем класс
ArgumentParser
, помогающий работать с командной строкой, и зададим описание скрипта. - Добавим аргумент, задаваемый ключом
’-t’
или’--token’
. В параметреhelp
указываем описание, показываемое при вызове скрипта с ключом-h
. - Переводим строки аргументов в объекты и присваиваем их как атрибуты к переменной.
Теперь, при запуске скрипта с ключом -t
, в переменной args.token
будет храниться значение введенного токена. Про остальные параметры и методы можно узнать в документации python.
Чтение и запись в файл конфигурации
Полученный токен хранится в конфигурационном файле. Рассмотрим код для доступа, чтения и записи значения:
Чтение и запись в файл конфигурации
Полученный токен хранится в конфигурационном файле. Рассмотрим код для доступа, чтения и записи значения:
config = configparser.ConfigParser()
config.read(expanduser('~') + "/.todoist")
token = args.token
if token is None:
token = config['Global']['TokenAPI']
else:
config['Global'] = {'TokenAPI': token}
with open(expanduser('~') + "/.todoist", 'w') as configfile:
config.write(configfile)
- Инициализируем
ConfigParser
и читаем файл из домашней директории пользователя.expanduser('~')
позволяет получить путь к домашней директории в любой операционной системе. - Читаем конфиг как словарь:
config['Global']['TokenAPI']
. Сначала обращаемся к секции со значением, следом — к ключу. - В блоке
else
записываем значение токена, если оно было указано при запуске. После конфигурационный файл записывается на диск.
Мне понравилось, как просто записать изменения в файл. В C# для этого надо открывать потоки, указывать дополнительную информацию, здесь это просто 2 строчки. Возьми это и запиши сюда, все.
Документация для ConfigParser. Информацию о вводе и выводе в Python 3.
Заключение
Знакомство с языком Python оставило приятное впечатление. Как минимум его стоит изучить на базовом уровне, чтобы автоматизировать происходящие вокруг вас процессы. Он также хорош для быстрого написания прототипа идеи, засевшей у вас в голове.
Полный скрипт TodoistOverdue.py
из статьи лежит в gist.
Полезные ссылки
— Как запускать скрипты в Mac Os X без указания полного пути. Stackoverflow. — Изучить питон за несколько минут (learnxinyminutes.com). Русская и английская версия. — Документация для Python 3.5.х.