Заметки с тегом
Python
Первый скрипт на Python

Желание изучить питон было давно. Я много где слышал что он хорошо подходит для прототипов, скриптов и небольших приложений. Он отличается высокой скоростью разработки и низким порогом вхождения. Динамичность — непривычно, но решаемо.

И вот, написал первый скрипт. Он оптимизирует перемещение на «сегодня» просроченных задач в тудуисте. Перенос в приложении выполняется в 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'))
  1. По ключу due_date_utc получаем дату в формате "Fri 26 Sep 2014 08:25:05 +0000". Выражением %a %d %b %Y %H:%M:%S %z переводим в понятный питону формат. Документация по значениям переменных из выражения.
  2. Находим разницу между текущей датой и датой полученного объекта.
  3. Актуализируем дату объекта, добавляя к нему полученную разницу дней.
  4. Переведем дату в строку используя %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()
  1. Инициализируем класс ArgumentParser, помогающий работать с командной строкой, и зададим описание скрипта.
  2. Добавим аргумент, задаваемый ключом ’-t’ или ’--token’. В параметре help указываем описание, показываемое при вызове скрипта с ключом -h.
  3. Переводим строки аргументов в объекты и присваиваем их как атрибуты к переменной.

Теперь, при запуске скрипта с ключом -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)
  1. Инициализируем ConfigParser и читаем файл из домашней директории пользователя. expanduser('~') позволяет получить путь к домашней директории в любой операционной системе.
  2. Читаем конфиг как словарь: config['Global']['TokenAPI']. Сначала обращаемся к секции со значением, следом — к ключу.
  3. В блоке else записываем значение токена, если оно было указано при запуске. После конфигурационный файл записывается на диск.

Мне понравилось, как просто записать изменения в файл. В C# для этого надо открывать потоки, указывать дополнительную информацию, здесь это просто 2 строчки. Возьми это и запиши сюда, все.

Документация для ConfigParser. Информацию о вводе и выводе в Python 3.

Заключение

Знакомство с языком Python оставило приятное впечатление. Как минимум его стоит изучить на базовом уровне, чтобы автоматизировать происходящие вокруг вас процессы. Он также хорош для быстрого написания прототипа идеи, засевшей у вас в голове.

Полный скрипт TodoistOverdue.py из статьи лежит в gist.

Полезные ссылки

— Как запускать скрипты в Mac Os X без указания полного пути. Stackoverflow. — Изучить питон за несколько минут (learnxinyminutes.com). Русская и английская версия. — Документация для Python 3.5.х.