Генерация фиктивных данных с Mimesis: Часть I
Nuances of programming
Mimesis — это библиотека для языка программирования Python, которая помогает генерировать фиктивные данные для различных целей. Библиотека написана с использованием средств, включенных в стандартную библиотеку языка Python, потому не имеет никаких сторонних зависимостей. На данный момент библиотека поддерживает 30 языковых стандартов (в числе которых и русский) и более 20 классов-провайдеров, предоставляющих разного рода данные.
Возможность генерировать фиктивные, но в то же время валидные данные бывает очень полезна при разработке приложений, которые подразумевают работу с базой данных. Ручное заполнение базы данных представляется довольно затратным по времени и трудоемким процессом, который выполняется как минимум в 3 этапа — это:
- Сбор необходимой информации.
- Постобработка собранных данных.
- Программирования генераторов данных.
Эта непростая задача по-настоящему усложняется в тот момент, когда требуется сгенерировать не 10-15 пользователей, а 100-150 тысяч пользователей (или иного рода данные). В этой и последующих статьях мы постараемся обратить ваше внимание на инструмент, который в разы упрощает процесс генерации тестовых данных, начальной загрузки базы данных и тестирования в целом.
Общая информация
Поддерживаемые языковые стандарты:

Список поддерживаемых классов-провайдеров постоянно расширяется. Все поддерживаемы поставщики данных перечислены тут.
Помимо перечисленных выше, поддерживаются так же специфичные для конкретных стран данные, которые можно импортировать из подпакета builtins:

Установка
Установка Mimesis производится как обычно, т.е посредством пакетного менеджера pip. Чтобы установить последнюю свежую версию библиотеки выполните следующую команду:
➜ ~ pip install mimesis
Если по каким-то причинам у вас не получается установить пакет с помощью pip, то попробуйте установить его вручную, как показано ниже:
(venv) ➜ git clone https://github.com/lk-geimfari/mimesis.git (venv) ➜ cd mimesis/ (venv) ➜ python3 setup.py install # или (venv) ➜ make install
Обращаем ваше внимание, что библиотека работает только на Python 3.5 +. Никаких планов по добавлению поддержки Python 2.7 у разработчиков нет.
Генерация
Изначально мы планировали показать генерацию данных на примере небольшого веб-приложения на Flask, но решили отказаться от этой идеи, по той причине, что не все знакомы с Flask и не все горят желанием это исправлять. Потому мы будем показывать все на чистом Python. В случае, если вы захотите перенести все в свой проект на Flask или Django, то вам нужно всего лишь определить статический метод, выполняющий все манипуляции связанные с текущей моделью и вызывать его в тот момент, когда нужно выполнить начальную загрузку БД, как показано в примере ниже.
Модель для Flask (Flask-SQLAlchemy) будет выглядеть как-то так:
class Patient(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True)
phone_number = db.Column(db.String(25))
full_name = db.Column(db.String(100))
weight = db.Column(db.String(64))
height = db.Column(db.String(64))
blood_type = db.Column(db.String(64))
def __init__(self, **kwargs):
super(Patient, self).__init__(**kwargs)
@staticmethod
def _bootstrap(count=2000, locale='en'):
from mimesis.providers import Personal
person = Personal(locale)
for _ in range(count):
patient = Patient(
email=person.email(),
phone_number=person.telephone(),
full_name=person.full_name(gender='female'),
weight=person.weight(),
height=person.height(),
blood_type=person.blood_type()
)
db.session.add(patient)
try:
db.session.commit()
except Exception:
db.session.rollback()
Переходим в shell-mode:
(venv) ➜ python3 manage.py shell
И генерируем данные, предварительно убедившись в том, что база данных и подопытная модель доступны.
>>> db <SQLAlchemy engine='sqlite:///db.sqlite'> >>> Patient <class 'app.models.Patient'> >>> Patient()._bootstrap(count=4000, locale='ru') # Сгенерировать 4к записей на русском языке.
Введение
Хотелось бы отметить, что мы будем приводить в примерах только базовые возможности библиотеки и, в основном, обойдемся несколькими наиболее часто встречающимися классами-провайдерами, ибо их слишком много, чтобы рассказывать обо всех в деталях. Если статья возбудит в вас интерес к библиотеке, то вы сможете найти полезные ссылки в самом конце статьи и самостоятельно все изучить.
Библиотека устроена довольно просто и все, что вам необходимо для того, чтобы начать работать с данным — это создать экземпляр класса-провайдера. Наиболее часто встречающиеся данные в веб-приложениях — это личные данные пользователя, такие как имя пользователя, имя, фамилия, возраст, кредитные данные и т.п. Для генерации таких данных существует специальный класс-провайдер — Personal(), который принимает код языкового стандарта в виде строки, как показано ниже:
>>> from mimesis import Personal
# Создаем экземпляр класса-провайдера с данными для исландского языка.
>>> person = Personal('is')
# Выводим исландские мужские имена.
>>> for _ in range(0, 3):
... person.full_name(gender='male')
`Karl Brynjúlfsson`
`Rögnvald Eiðsson`
`Vésteinn Ríkharðsson`
Практически каждое веб-приложение требует ввода e-mail адреса при регистрации. Библиотека, разумеется поддерживает возможность генерировать e-mail адреса и делается это с помощью метода email() класса Personal(), как показано ниже:
# Женский: >>> person.email(gender='female') >>> 'lvana6108@gmail.com' # Мужской: >>> person.email(gender='male') 'john2454@yandex.com'
В способе, что был приведен выше кроется небольшая проблема, которая может несколько загрязнять код, если в приложении используется не один единственный класс-провайдер, а несколько. В таких случаях следует использовать объект Generic(), который дает доступ ко всем провайдерам из одного единственного объекта, как показано ниже:
>>> from mimesis import Generic
>>> # Согласно стандарту ISO 639-1, pl - это код Польши.
>>> g = Generic('pl')
>>> g.personal.full_name()
'Lonisława Podsiadło'
>>> g.datetime.birthday(readable=True)
'Listopad 11, 1997'
>>> g.personal.blood_type()
'A−'
Комбинирование данных дает большой простор. К примеру можно создать фиктивных держателей (женского пола) карты Visa (или MasterCard, Maestro):
>>> user = Personal('en')
>>> def get_card(sex='female'):
... owner = {
... 'owner': user.full_name(sex),
... 'exp_date': user.credit_card_expiration_date(maximum=21),
... 'number': user.credit_card_number(card_type='visa')
... }
... return owner
>>> for _ in range(0, 3):
... get_card()
Вывод:
{'exp_date': '02/20', 'owner': 'Laverna Morrison', 'card_number': '4920 3598 2121 3328'}
{'exp_date': '11/19', 'owner': 'Melany Martinez', 'card_number': '4980 9423 5464 1201'}
{'exp_date': '01/19', 'owner': 'Cleora Mcfarland', 'card_number': '4085 8037 5801 9703'}
Как уже говорилось выше, библиотека поддерживает более 20 классов-провайдеров, которые содержат данные на все случаи жизни (если нет, то ждем PR с исправлением этого ужасного недоразумения). К примеру, если вы разрабатываете приложение ориентированное на грузоперевозки или на иную деятельность, связанную с транспортом и вам необходимо сгенерировать модели транспорта, то вы с легкостью сможете сделать это, воспользовавшись классом-провайдером Transport(), который содержит данные о транспорте:
>>> from mimesis import Transport >>> trans = Transport() >>> for _ in range(0, 5): ... trans.truck() 'Seddon-2537 IM' 'Karrier-7799 UN' 'Minerva-5567 YC' 'Hyundai-2808 XR' 'LIAZ-7174 RM'
Ну или можно указать маску модели транспорта:
>>> for _ in range(0, 5): ... trans.truck(model_mask="##@") # # - числа, @ - буквы
Henschel-16G Bean-44D Unic-82S Ford-05Q Kalmar-58C
Нередко при тестировании веб-приложений (тестирование блога — яркий пример) возникает необходимость сгенерировать текстовые данные (текст, предложение, тег и.т.п.). Вбивать вручную текст при тестировании — это долго и скучно и Mimesis позволяет этого избежать, благодаря классу-провайдеру Text():
>>> from mimesis import Text
>>> text = Text('ru')
>>> text.text(quantity=3) # quantity - показатель количества предложений.
'Язык включает в себя средства порождения параллельных легковесных процессов и их взаимодействия через обмен асинхронными сообщениями в соответствии с моделью акторов. Python поддерживает несколько парадигм программирования, в том числе структурное, объектно-ориентированное, функциональное, императивное и аспектно-ориентированное. Например, определение функции, которое использует сопоставление с образцом, для выбора одного из вариантов вычисления или извлечения элемента данных из составной структуры, напоминает уравнение.'
Можно получить список случайных слов:
>>> text = Text('pt-br')
>>> text.words(quantity=5)
['poder', 'de', 'maior', 'só', 'cima']
Cгенерировать название улицы:
>>> from mimesis import Address
>>> address = Address('ru')
>>> address.address()
'ул. Хабаровская 651'
Получить название субъекта/штата/провинции странны, к которой относится выбранный языковой стандарт. В данном случае — это субъект Российской Федерации:
>>> address.state() 'Кировская область'
Сгенерировать координаты:
>>> address.coordinates()
{'latitude': -28.362892454682246, 'longitude': 11.512065821275826}
В библиотеке так же есть средства для романизации кириллических языков (на момент написания статьи поддерживаются только русский и украинский):
>>> from mimesis.decorators import romanized
>>> @romanized('ru')
... def name_ru():
... return 'Вероника Денисова'
...
>>> @romanized('uk')
>>> def name_uk():
... return 'Емілія Акуленко'
...
>>> name_ru()
'Veronika Denisova'
>>> name_uk()
'Emіlіja Akulenko'
На самом деле возможностей очень много и можно придумать огромное количество куда более наглядных примеров, в контексте которых данные будут выглядеть более ценными, чем выше. Мы ждем таких примеров от вас — читателей. Мы будем очень рады прочитать об успешном опыте применении библиотеки в ваших проектах.