Python
Django
21 December 2016

Генерация фиктивных данных с Mimesis: Часть I

From Sandbox
image

Mimesis — это библиотека для языка программирования Python, которая помогает генерировать фиктивные данные для различных целей. Библиотека написана с использованием средств, включенных в стандартную библиотеку языка Python, потому не имеет никаких сторонних зависимостей. На данный момент библиотека поддерживает 30 языковых стандартов (в числе которых и русский) и более 20 классов-провайдеров, предоставляющих разного рода данные.


Возможность генерировать фиктивные, но в то же время валидные данные бывает очень полезна при разработке приложений, которые подразумевают работу с базой данных. Ручное заполнение базы данных представляется довольно затратным по времени и трудоемким процессом, который выполняется как минимум в 3 этапа — это:


  1. Сбор необходимой информации.
  2. Постобработка собранных данных.
  3. Программирования генераторов данных.

Эта непростая задача по-настоящему усложняется в тот момент, когда требуется сгенерировать не 10-15 пользователей, а 100-150 тысяч пользователей (или иного рода данные). В этой и двух последующих статьях мы постараемся обратить ваше внимание на инструмент, который в разы упрощает процесс генерации тестовых данных, начальной загрузки базы данных и тестирования в целом.


Общая информация


Поддерживаемые языковые стандарты:


Код Название
1 cs Чешский
2 da Датский
3 de Немецкий
4 de-at Австрийский немецкий
5 de-ch Швейцарский немецкий
6 en Английский
7 en-au Австралийский английский
8 en-ca Канадский английский
9 en-gb Британский английский
10 es Испанский
11 es-mx Мексиканский испанский
12 fa Персидский (Фарси)
13 fi Финский
14 fr Французский
15 hu Венгерский
16 is Исландский
17 it Итальянский
18 ja Японский
19 ko Корейский
20 nl Нидерландский
21 nl-be Бельгийский нидерландский
22 no Норвежский
23 pl Польский
24 pt Португальский
25 pt-br Бразильский португальский
26 ru Русский
27 sv Шведский
28 tr Турецкий
29 uk Украинский
30 zh Китайский

Список поддерживаемых классов-провайдеров постоянно расширяется. Все поддерживаемы поставщики данных перечислены тут.


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


Провайдер Методы
1 USASpecProvider tracking_number(), ssn(), personality()
2 JapanSpecProvider full_to_half(), half_to_full()
2 RussiaSpecProvider patronymic(), passport_series(), passport_number(), snils()
2 BrazilSpecProvider cpf(), cnpj()

Установка


Установка 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'

На самом деле возможностей очень много и можно придумать огромное количество куда более наглядных примеров, в контексте которых данные будут выглядеть более ценными, чем выше. Мы ждем таких примеров от вас — читателей. Мы будем очень рады прочитать об успешном опыте применении библиотеки в ваших проектах.


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


Здесь вы можете найти вторую часть статьи.
Здесь вы сможете прочитать дополненный вариант этой статьи и много других интересных статей на разные темы.


Github: lk-geimfari/mimesis
Read the Docs: mimesis


Спасибо за внимание и удачных вам тестов!


+44
23.3k 233
Comments 40
Top of the day