В АРХИВЕ
xahotaf452@hxqmail.com————————————
ПОЯСНЕНИЯ
Скрипт для получения задач пользователей
Позволяет получить задачи по пользователям и сохранить инфу в файлы. Похож на генерацию файлов sitemap.xml для сайтов. Подразумевается использование с периодическим запуском на фоне как демона.
Требования и использование
Для работы скрипта необходим интерпретатор Python 3
Запуск python /path/to/script/get_users_tasks.py
Вариант 2 - актуализация всех файлов пачкой
Если требуется чтобы файлы актуализировались все пачкой или никак. Если юзеров и задач будет огромное кол-во, лучше не хранить в памяти все данные для создания файлов, а брать по несколько и записывать на диск, дабы не поймать out of memory.
Возможный алгоритм
Копируем боевую директорию DIR1 в DIR2. Генерируем файлы по актуальным данным в DIR2. По завершении создаем симлинк TASKS на DIR2 ln -s /path/dir2 /path/tasks. Теперь внешняя программа (человек) будет тянуть свежие файлы из DIR2. После первой итерации скрипта как демона предусматриваем смену симлинка, также после генерации rm /path/tasks.
Преимущества:
изолированность версий, на бою будут все актуальные файлы одной версии.
Недостатки:
возможен простой внешней программы, которая использует файлы, если сервер упадет между выполнением команд rm /path/tasks …server down… ln -s /path/dir{n} /path/tasks. Нивелируется автоматической проверкой и исправлением после подъема сервера.
требует больше места на харде, т.к. полностью копируется текущая актуальная директория.
Вариант 3 - используем СУБД
Храним данные в BLOB полях, весь процесс строим на транзакциях. Можно организовать динамическую генерацию файлов по запросу скриптом-прокладкой. Например GoogleBot пришел за /path/sitemap_1.xml, /path/sitemap_2.xml, а статичных файлов нет, там запросы обрабатывает дежурный скрипт, который генерирует сайтмап на лету и отдает.
Преимущества:
лучший вариант для данного рода задач.
Недостатки:
придется переделать прием входных данных у внешней программы с файлов на БД, в том числе скриптом обрабочиком.
————————————
ТЗ
Есть API для получения списка задач и api для получения списка юзеров:
https://jsonplaceholder.typicode.com/todoshttps://jsonplaceholder.typicode.com/usersИспользуя только эти API составить отчёты по всем юзерам в отдельных текстовых файлах.
После запуска скрипта, рядом должна появиться директория “tasks” с текстовыми файлами. Файл называть по username пользователя в формате “Antonette.txt”
Внутри файла на первой строке писать полное имя, и рядом в < > записывать email. Через пробел от email записывать время составления отчёта в формате 23.09.2020 15:25
На второй строке записывать название компании, в которой работает юзер.
Третья строка должна быть пустой.
На четвёртой строке “Завершённые задачи:” и далее список названий завершённых задач.
После завершённых задач через пустую строку записать “Оставшиеся задачи:” и вывести остальные задачи.
Если название задачи больше 50 символов, то обрезать до 50 символов и добавить троеточие.
Пример файла:
```
Ervin Howell <
Shanna@melissa.tv> 23.09.2020 15:25
Deckow-Crist
Завершённые задачи:
distinctio vitae autem nihil ut molestias quo
Оставшиеся задачи:
suscipit repellat esse quibusdam voluptatem incidu…
laborum aut in quam
```
Если файл для пользователя уже существует, то существующий файл переименовать, добавив в него время составления этого старого отчёта в формате “Antonette_2020-09-23T15:25.txt”
Таким образом, актуальный отчёт всегда будет без даты в названии. Старые отчёты не удаляются, а переименовываются.
Код должен быть чистым, без необоснованных повторений, с выделенем функций, где это уместно, с говорящими именами.
Код сделать максимально эффективным, но не в ущерб читабельности. Подсказка: следует избегать частых записей на диск.
Предусмотреть возможные сбои в сети или при записи на диск. Не должно быть наполовину сформированных файлов. Либо файл есть и он целиком корректный, либо его нет.
Если по юзеру однажды был создан отчёт, то всегда должен существовать актуальный отчёт без даты в названии. Не должно быть такого, что из-за сбоя в сети или т.п. остались только файлы с датами в названиях.
Если какие-то моменты не обговорены в задаче, то продумайте плюсы и минусы возможных вариантов, и выберите наиболее подходящий на ваш взгляд, чтобы потом можно было обосновать своё решение.
Предусмотреть крайние случаи (у пользователя нет задач, и т.п.).
Код должен быть оформлен по pep8.
Использовать местное время.
Программа должна корректно работать на linux (Debian, Ubuntu).
Можно использовать любые библиотеки.
————————————
КОД
# -*- coding: utf-8 -*-
import os
import requests
import json
import time
TASKS_DIR = os.path.dirname(__file__) + '/tasks'
USERS_GET_LINK = 'https://jsonplaceholder.typicode.com/users'
TASKS_GET_LINK = 'https://jsonplaceholder.typicode.com/todos'
def error(text, is_exit=True):
print(text)
if is_exit:
exit(0)
if not os.path.isdir(TASKS_DIR):
try:
os.mkdir(TASKS_DIR)
except Exception:
error(u'Не удалось создать боевую директорию')
try:
users_data = requests.get(USERS_GET_LINK)
except Exception:
error(u'Не удалось получить пользователей | get_http_error')
users_data = users_data.text
try:
users_data_json = json.loads(users_data)
except Exception:
error(u'Не удалось получить пользователей | json_error')
try:
tasks_data = requests.get(TASKS_GET_LINK)
except Exception:
error(u'Не удалось получить задачи | get_http_error')
tasks_data = tasks_data.text
try:
tasks_data_json = json.loads(tasks_data)
except Exception:
error(u'Не удалось получить задачи | json_error')
files_arr = []
for user in users_data_json:
file_data = user['name'] + '<' + user['email'] + '> ' +\
time.strftime('%d.%m.%Y %H:%M', time.localtime()) + '\n' +\
user['company']['name'] + '\n\n'
compl_tasks = ''
uncompl_tasks = ''
for task in tasks_data_json:
if task['userId'] == user['id']:
if len(task['title']) > 50:
task_title = task['title'][:50] + '...'
else:
task_title = task['title']
if task['completed']:
compl_tasks += task_title + '\n'
else:
uncompl_tasks += task_title + '\n'
file_data += u'Завершённые задачи:\n' + compl_tasks + '\n'
file_data += u'Оставшиеся задачи:\n' + uncompl_tasks
files_arr.append({'username': user['username'], 'data': file_data})
old_files_c = 0
new_files_c = 0
for file in files_arr:
username = file['username']
data = file['data']
file_path = TASKS_DIR + '/' + username + '.txt'
if os.path.isfile(file_path):
new_path = TASKS_DIR + '/' + username + '_' +\
time.strftime('%Y-%m-%dT%H:%M',
time.localtime(os.path.getctime(file_path))) + '.txt'
try:
os.rename(file_path, new_path)
old_files_c += 1
except Exception:
error(u'Не удалось переименовать старый файл ' + file_path +
' в ' + new_path + '\n', False)
try:
with open(file_path, 'w') as f:
f.write(data.encode('utf-8'))
new_files_c += 1
except Exception:
error(u'Не удалось создать актуальный файл ' + file_path + '\n', False)
print(u'Успешно создано новых файлов ' + str(new_files_c) +
u'\nПереименованно старых: ' + str(old_files_c))