5.1. Пример создания задач¶
Этот пример демонстритует, как можно устанавливать соединение с базой данных, создавать задачи и связывать их между собой без использования графического интерфейса Cerebro. Также в модуле продемонстрировано создание сообшений и прикладывание к ним файлов.
Пример находится в папке «py_cerebro/examples» серверного модуля.
py_cerebro/examples/create_tasks.py
# -*- coding: utf-8 -*- """ Примеры создания задач. Этот модуль демонстритует, как можно устанавливать соединение с базой данных, создавать задачи и связывать их между собой без использования графического интерфейса Cerebro. Также в модуле продемонстрировано создание сообшений и прикладывание к ним файлов. Модуль использует пакет py_cerebro (для Python 3.x), который входит в дистрибутив service-tools (http://cerebrohq.com/distribs/service-tools.zip). Пакет py_cerebro содержит модули для установки соединения с базой данных и для доступа к файловому хранилищу(Cargador). Пакет py_cerebro использует сторонний пакет postgresql (http://python.projects.postgresql.org/) для осущевстления доступа к базе данных PostgreSQL. Возможно вам придется дополнительно установить этот пакет. Модуль содержит функции: create_and_link_tasks - пример создания задач и установления между ними связей. make_thumnails - для генерации эскизов к видео файлам и изображениям """ import fnmatch import sys import os import subprocess import datetime local_dir = os.path.realpath(__file__).replace('\\', '/').rsplit('/', 1)[0] backend_dir = local_dir + '/../..' sys.path.append(backend_dir) import py_cerebro from py_cerebro import dbtypes # в этом модуле описаны различные константы, такие как поля данных, флаги и т.п. # Переменные, которые вам возможно придется изменить, чтобы преспособить скpипт для вашей сети #Следующие два параметра, хост и порт - это наш главный сервер с базой данных. #У вас эти параметры могут быть иными, если вы используете свою базу данных database_host = 'cerebrohq.com' database_port = 45432 cargador_host = 'ss' # Cетевой адрес машины, где работает севрис каргадор. # Может быть задано сетевое имя или IP адрес. 'ss' - это имя нашего сервера, у вас этот параметр скорее всего будет иным. cargador_xmlrpc_port = 4040 # Порт 4040 - это порт для запросов по xmlrpc протоколу. #У вас порт может быть иным, подробнее об этом смотрите в комментариях модуля cargador пакета py_cerebro. cargador_http_port = 4080 # Порт 4080 - это порт для запросов по http протоколу. #У вас порт может быть иным, подробнее об этом смотрите в комментариях модуля cargador пакета py_cerebro. project_name = 'Test project' # Имя проекта для тестового добавления задач. #Вы можете выбрать любой свой проект mirada_path = '//ss/front/cerebro/mirada.exe' # Путь, откуда запускать мираду для генерации эскизов. #У вас этот параметр скорее всего будет иным. Подробнее смотрите в функции def create_and_link_tasks(db_user, db_password): """ db_user и db_password это логин и пароль пользователя Cerebro В этом примере мы создадим в проекте задачу и две подзадачи. У задачи выставим время начала, у подзадач запланируем время исполнения и свяжем их между собой. Также мы создадим у подзадач сообщения типа постановка задачи и приложим к ним файлы. Мы не будем в этом примере самостоятельно писать sql-запросы, а воспольуемся функцями класса database.Database, которые по сути являются обертками над sql-запросами. Описание всех функций смотрите в модуле database пакета py_cerebro. Пример вызова функции: :: import create_tasks create_tasks.create_and_link_tasks('user', 'password') :: """ def find(f, seq): # поиск объектов в списке for item in seq: if f(item): return item try: db = py_cerebro.database.Database(database_host, database_port) # Устанавливаем соединение с базой данных if db.connect_from_cerebro_client() != 0: # пробуем установить соединение с помощью запущенного клиента Cerebro. # Если не выходит, устанавливаем с помощью логина и пароля db.connect(db_user, db_password) root_tasks = db.root_tasks() # Получаем список корневых задач проектов. # Ищем нужную корневую задачу проекта в который и будем добовлять задачи root_task = find(lambda val: val[dbtypes.TASK_DATA_NAME] == project_name, root_tasks) # Создаем задачу в проекте new_task_id = db.add_task(root_task[dbtypes.TASK_DATA_ID], 'New Test Task') """ Функция add_task принимает на вход два агрумента: - идентификатор родительской задачи, в данном случаи идентификатор корневой задачи проекта - имя задачи, Будте внимательны имя задачи имеет ограничения. Подробнее о них смотрите в описании функции add_task. Результат функции - идентификатор новой задачи. """ # Устанавливаем время начала задачи в теушее время """ Время начала задачи устанавливается в днях от 01.01.2000 в UTC Подробнее о этом смотрите в описании функции task_set_start. """ datetime_now = datetime.datetime.utcnow() datetime_2000 = datetime.datetime(2000, 1, 1) timedelta = datetime_now - datetime_2000 days = timedelta.total_seconds()/(24*60*60) db.task_set_start(new_task_id, days) # Создаем две подзадачи к новой задаче new_subtask_id_1 = db.add_task(new_task_id, 'New Test Subtask 1') new_subtask_id_2 = db.add_task(new_task_id, 'New Test Subtask 2') # Добовляем к подзадачам постановки задач с файлами def_id_1 = db.add_definition(new_subtask_id_1, 'Do something 1') def_id_2 = db.add_definition(new_subtask_id_2, 'Do something 2') filename1 = local_dir + '/test.png' # файл для первой подзадачи thumbnails1 = make_thumnails(filename1) # генерация эскизов для файла filename1 filename2 = local_dir + '/test.mp4' # файл для второй подзадачи thumbnails2 = make_thumnails(filename2) # генерация эскизов файла filename2 # Создаем объект для добавления файлов в файловое хранилище (Cargador) carga = py_cerebro.cargador.Cargador(cargador_host, cargador_xmlrpc_port, cargador_http_port) # Добовляем к сообщениям типа постановки задач файлы и, заодно, экспортируем их в хранилище db.add_attachment(def_id_1, carga, filename1, thumbnails1, '', False) db.add_attachment(def_id_2, carga, filename2, thumbnails2, '', False) """ Параметр carga, передается для экспортирования файла в файловое хранилише. Подробнее об этом смотрите в модуле cargador. Последний параметр означает, будет ли файл добавлен как линк, без экспорта в хранилище (значение True), или же он будет экспортитован (значение False) Подробнее об этом смотрите в описании функции add_attachment. """ # Удаляем сгенерированные эскизы, поскольку мы их уже экспортировали в хранилище for f in thumbnails1: os.remove(f) for f in thumbnails2: os.remove(f) # Устанавливаем запланированное время на подзадачи db.task_set_planned_time(new_subtask_id_1, 12.5) # первой подзадаче устанавливаем 12 с половиной часов db.task_set_planned_time(new_subtask_id_2, 30) # второй подзадаче устанавливаем 30 часов # Связываем подзадачи db.set_link_tasks(new_subtask_id_1, new_subtask_id_2) """ Эта связь значит, что вторая подзадача начнется после окончания первой подзадачи """ except Exception as err: print(err) def make_thumnails(filename): """ Принимает на вход полный путь до файла видео или изображения и генерирует эскизы к ним :returns: список путей до файлов эскизов. Пример вызова функции: :: import create_tasks filename = 'c:/temp/file.mov' thumbnails = create_tasks.create_and_link_tasks(filename) :: Генерация эскизов: Если файл является изображением или видео, то можно добавить для него уменшенные эскизы. Можно добавить до 3-х эскизов (первый, средний, последний кадры). Для генерации эскизов можно использовать программу Mirada. Она постовляется вместе с дистрибутивом Cerebro. Можно использовать и другие программы для генерации, например, ffmpeg. """ #Пример генерации эскизов с помощью Mirada. if os.path.exists(filename) == False or os.path.exists(mirada_path) == False: return list() gen_path = os.path.dirname(filename) # В качестве директории для генерации эскизов возьмем директорию добавляемого файла # Запускаем мираду с необходимыми ключами res_code = subprocess.call([mirada_path, filename, '-temp', gen_path, '-hide']) #-temp - директория для генерации эскизов #-hide - ключ запуска мирады в скрытом режиме (без загрузки графического интерфейса) для генерации табнейлов. if res_code != 0: raise Exception("Mirada returned bad exit-status.\n" + mirada_path) #Ищем сгенерированные мирадой эскизы. #Имени эскиза формируется из имени файла, даты и времени генерации - filename_yyyymmdd_hhmmss_thumb[number].jpg #Например: test.mov_20120305_112354_thumb1.jpg - первый эскиз видео-файла test.mov thumbnails = list() for f in os.listdir(gen_path): if fnmatch.fnmatch(f, os.path.basename(filename) + '_*_thumb?.jpg'): thumbnails.append(gen_path + '/' + f) thumbnails.sort() """ #Пример генерации эскизов с помощью ffmpeg. #Для того, чтобы генерить эскизы с помощью ffmpeg, нужно заранее знать длительность видео, #чтобы корректно получить средний и последний кадры. #Возьмем к примеру ролик длительностью в 30 секунд. thumbnails = list() # список файлов для эскизов thumbnails.append(filename + '_thumb1.jpg') thumbnails.append(filename + '_thumb2.jpg') thumbnails.append(filename + '_thumb3.jpg') subprocess.call(['ffmpeg', '-i', filename, '-s', '512x512', '-an', '-ss', '00:00:00', '-r', 1, '-vframes', 1, '-y', thumbnails[0]]) subprocess.call(['ffmpeg', '-i', filename, '-s', '512x512', '-an', '-ss', '15:00:00', '-r', 1, '-vframes', 1, '-y', thumbnails[1]]) subprocess.call(['ffmpeg', '-i', filename, '-s', '512x512', '-an', '-ss', '30:00:00', '-r', 1, '-vframes', 1, '-y', thumbnails[2]]) # Описание ключей вы можете посмотреть в документации к ffmpeg """ return thumbnails