Привет, Хабр! Думаю, многие сталкивались с необходимостью генерации тысячи пользователей. Вручную - не вариант, слишком долго. В данной статье разберу библиотеку Faker. Это генератор реалистичных тестовых данных, который превращает заполнение базы и создание демо-контента из рутины в дело пары строк кода. В статье продемонстрирую, как генерировать тысячи правдоподобных записей на русском, заполнять БД и создавать собственные типы данных для ваших проектов.
Введение
Faker
- очень полезная библиотека для генерации правдоподобных фейковых данных. Поможет решить следующие задачи:
Протестировать форму регистрации без ручного ввода 100 пользователей
Заполнить базу данных реалистичными данными
Создать макет интерфейса с правдоподобным контентом
Сгенерировать данные для ML-моделей
Оценим пользу библиотеки на практическом примере:
Пример боли без Faker
:
# Ручное создание тестовых данных, что априори неудобно
users = [
{"name": "Иван Иванов", "email": "test1@test.com", "phone": "1234567890"},
{"name": "Петр Петров", "email": "test2@test.com", "phone": "0987654321"},
# и так 100 раз :)
]
Решение с Faker
:
# Автоматическая генерация
from faker import Faker
fake = Faker('ru_RU')
users = [{
"name": fake.name(),
"email": fake.email(),
"phone": fake.phone_number()
} for _ in range(100)]
Далее, базовый пример инициализации нашего генератора:
from faker import Faker
# Простая инициализация (английский по умолчанию)
fake = Faker()
# С локализацией (русские данные)
fake_ru = Faker('ru_RU')
# С несколькими провайдерами
fake = Faker()
fake.add_provider('faker.providers.person.ru_RU')
fake.add_provider('faker.providers.address.ru_RU')
И, немного про локализацию:
fake_en = Faker('en_US')
fake_ru = Faker('ru_RU')
print(f"EN: {fake_en.name()}") # John Smith
print(f"RU: {fake_ru.name()}") # Иванов Иван
# В разных локализациях - разные форматы имён, адресов и прочего
Разбор провайдеров данных
1. Персональные данные
# Личная информация
person = {
"full_name": fake_ru.name(), # Иванов Иван Сергеевич
"first_name": fake_ru.first_name(), # Иван
"last_name": fake_ru.last_name(), # Иванов
"middle_name": fake_ru.middle_name(), # Сергеевич
"gender": fake_ru.random_element(["M", "F"]), # M или F
"age": fake_ru.random_int(18, 90), # Случайный возраст
"birthdate": fake_ru.date_of_birth(minimum_age=18, maximum_age=90) # 1990-05-15
}
# Документы (особенно полезно для РФ)
documents = {
"inn": fake_ru.inn(), # 123456789012
"inn_individual": fake_ru.inn_individual(), # Для физических лиц
"inn_legal": fake_ru.inn_legal(), # Для юридических лиц
"snils": fake_ru.snils(), # 123-456-789 00
"passport": fake_ru.passport_number() # 12 34 567890
}
print("Персональные данные:")
for key, value in person.items():
print(f" {key}: {value}")
2. Адреса и контакты
# Подробный адрес
address = {
"full_address": fake_ru.address(), # г. Москва, ул. Ленина, д. 15
"postcode": fake_ru.postcode(), # 123456
"city": fake_ru.city(), # Москва
"street": fake_ru.street_name(), # ул. Ленина
"building": fake_ru.building_number(), # д. 15
"region": fake_ru.region(), # Московская область
"country": fake_ru.country() # Россия
}
# Контактная информация
contacts = {
"email": fake_ru.email(), # ivanov@example.com
"personal_email": fake_ru.free_email(), # ivanov@gmail.com
"work_email": fake_ru.company_email(), # ivanov@company.com
"phone": fake_ru.phone_number(), # +7 (123) 456-78-90
"mobile": fake_ru.phone_number() # +7 (912) 345-67-89
}
print("Адрес и контакты:")
for key, value in {**address, **contacts}.items():
print(f" {key}: {value}")
3. Финансовые данные
# Банковская информация
banking = {
"credit_card": fake_ru.credit_card_number(), # 1234 5678 9012 3456
"card_expire": fake_ru.credit_card_expire(), # 05/25
"cvv": fake_ru.credit_card_security_code(), # 123
"card_provider": fake_ru.credit_card_provider(), # Visa
"bank": fake_ru.bank(), # Сбербанк
"bic": fake_ru.bic(), # 044525225
"account": fake_ru.bban() # 40702810123456789012
}
# Транзакции и цены
finance = {
"amount": fake_ru.random_int(100, 100000), # Сумма
"price": fake_ru.pricetag(), # ₽1,234.56
"currency": fake_ru.currency(), # ('RUB', 'Рубль')
"cryptocurrency": fake_ru.cryptocurrency() # ('BTC', 'Bitcoin')
}
print("Финансовые данные:")
for key, value in {**banking, **finance}.items():
print(f" {key}: {value}")
4. Бизнес и компании
# Компания и работа
business = {
"company": fake_ru.company(), # ООО "Ведро и мыло"
"company_suffix": fake_ru.company_suffix(), # ООО, ЗАО, ИП
"catch_phrase": fake_ru.catch_phrase(), # Инновационные решения
"bs": fake_ru.bs(), # Масштабируемые веб-сервисы
"job": fake_ru.job(), # Менеджер по продажам
"industry": fake_ru.random_element([
"IT", "Маркетинг", "Финансы", "Розница"
])
}
print("Бизнес данные:")
for key, value in business.items():
print(f" {key}: {value}")
5. Интернет
# Интернет данные
internet = {
"url": fake_ru.url(), # https://example.com
"domain": fake_ru.domain_name(), # example.com
"ipv4": fake_ru.ipv4(), # 192.168.1.1
"ipv6": fake_ru.ipv6(), # 2001:db8::1
"mac_address": fake_ru.mac_address(), # 00:1A:2B:3C:4D:5E
"user_agent": fake_ru.user_agent(), # Browser info
"username": fake_ru.user_name(), # ivanov123
"password": fake_ru.password(length=12) # Secure password
}
print("Интернет данные:")
for key, value in internet.items():
print(f" {key}: {value}")
Теперь стоит понять, где и как можно на практике применять данную библиотеку:
Генерация юзеров для тестирования
def generate_test_users(count=10): # где 10 - кол-во сгенерированных пользователей
"""Генерация тестовых пользователей для системы"""
users = []
for i in range(count):
user = {
"id": i + 1, # Уникальный идентификатор, начинается с 1
"personal_info": {
"name": fake_ru.name(), # Случайное ФИО на русском
"birth_date": fake_ru.date_of_birth().isoformat(), # Дата рождения в формате ISO
"gender": fake_ru.random_element(["M", "F"]), # Пол (М/Ж)
"documents": {
"passport": fake_ru.passport_number(), # Номер паспорта
"snils": fake_ru.snils() # Номер СНИЛС
}
},
"contact_info": {
"email": fake_ru.email(), # Электронная почта
"phone": fake_ru.phone_number(), # Номер телефона
"address": fake_ru.address() # Адрес
},
"work_info": {
"company": fake_ru.company(), # Название компании
"position": fake_ru.job(), # Должность
"salary": fake_ru.random_int(30000, 200000) # Зарплата от 30к до 200к
},
"system_info": {
"registration_date": fake_ru.date_this_year().isoformat(), # Дата регистрации
"last_login": fake_ru.date_time_this_month().isoformat(), # Последний вход
"is_active": fake_ru.boolean(chance_of_getting_true=80) # 80% активных пользователей
}
}
users.append(user)
return users
# Вывод результата
test_users = generate_test_users(5)
for user in test_users:
print(f" {user['personal_info']['name']}")
print(f" {user['contact_info']['email']}")
print(f" {user['work_info']['position']}")
print("---")
Пример вывода:
Иванов Сергей Петрович
ivanov.sergey@mail.ru
Менеджер по продажам
---
Смирнова Анна Владимировна
smirnova.anna@gmail.com
Веб-разработчик
---
Заполнение БД PostgreSQL
import psycopg2
from faker import Faker
import logging
class DatabaseFiller:
def __init__(self, db_config):
self.fake = Faker('ru_RU') # Инициализация с русской локалью
self.db_config = db_config # Сохранение подключения к БД
self.conn = None
def connect(self):
"""Подключение к базе данных"""
try:
self.conn = psycopg2.connect(**self.db_config)
logging.info("Успешное подключение к БД")
except Exception as e:
logging.error(f"Ошибка подключения: {e}")
raise
def fill_users_table(self, count=100):
"""Заполнение таблицы пользователей"""
cursor = self.conn.cursor()
for _ in range(count):
user_data = (
self.fake.name(), # Случайное ФИО
self.fake.email(), # Случайный email
self.fake.phone_number(), # Случайный номер телефона
self.fake.address(), # Случайный адрес
self.fake.date_of_birth(), # Случайная дата рождения
self.fake.boolean() # Случайное булево значение (True/False)
)
cursor.execute("""
INSERT INTO users (name, email, phone, address, birth_date, is_active)
VALUES (%s, %s, %s, %s, %s, %s)
""", user_data)
self.conn.commit()
cursor.close()
logging.info(f"Добавлено {count} пользователей")
# Использование
db_config = {
'host': 'localhost',
'database': 'test_db',
'user': 'postgres',
'password': 'password'
}
filler = DatabaseFiller(db_config)
filler.connect()
filler.fill_users_table(1000) # Заполнение таблицы 1000 тестовыми пользователями
Для заполнения БД большими объемами информации (10к+ записей) используйте bulk-операции (executemany
) и отключайте индексы на время вставки, это в разы ускорит процесс генерации.
data = [(fake.name(), fake.email()) for _ in range(10000)]
cursor.executemany("INSERT INTO users (name, email) VALUES (%s, %s)", data)
Создание кастомного провайдера
Одной из главных особенностей является возможность создания кастомного провайдера, что значительно расширяет функционал. Вы можете генерировать абсолютно любые данные под специфические задачи. Посмотрим на примере:
Импорт необходимых модулей
from faker import Faker
from faker.providers import BaseProvider
import random
Где:
Faker - основной класс для генерации фейковых данных
BaseProvider - базовый класс, от которого наследуются все провайдеры
random - стандартный модуль Python для генерации случайных значений
Сама функция создания провайдера:
class RussianBusinessProvider(BaseProvider):
"""Кастомный провайдер для российского бизнеса"""
Класс наследуется от BaseProvider
, что даёт доступ ко всем методам Faker.
Что это значит?
BaseProvider
содержит набор фундаментальных методов, которые используются внутри всех других провайдеров. Самый главный - self.generator
. Это ссылка на основной объект Faker
, который управляет всеми провайдерами и генерацией случайных значений.
Вы можете использовать его для прямого доступа к любому провайдеру:
self.generator.address.city()
Практический пример
Допустим, Вы хотите создать свой собственный провайдер для генерации данных, специфичных для вашего приложения (например, тестовых пользователей вашей системы).
Без наследования от BaseProvider
вам пришлось бы создавать экземпляр Faker внутри класса и работать с ним, что менее удобно и эффективно.
С наследованием от BaseProvider
это делается просто и правильно:
from faker.providers import BaseProvider
# Ваш кастомный провайдер наследуется от BaseProvider
class MyCustomProvider(BaseProvider):
# Теперь у этого метода есть доступ ко всем возможностям Faker
def custom_user(self):
# Используем стандартные провайдеры Faker для создания данных
first_name = self.generator.first_name()
last_name = self.generator.last_name()
email = self.generator.email()
department = self.random_element(elements=('IT', 'HR', 'Sales', 'Marketing'))
# Формируем данные в нужном нам формате
return {
'name': f'{first_name} {last_name}',
'email': email,
'department': department,
'employee_id': self.generator.unique.random_number(digits=6)
}
# Как это использовать:
from faker import Faker
# Создаем экземпляр Faker
fake = Faker()
# Добавляем наш кастомный провайдер к Faker
fake.add_provider(MyCustomProvider)
# Теперь Faker умеет генерировать и наших пользователей!
user_data = fake.custom_user()
print(user_data)
Вывод следующий (каждый раз разный):
{
"name": "Emily Johnson",
"email": "emily.johnson@example.com",
"department": "IT",
"employee_id": 384721
}
По итогу, наследование от BaseProvider
- "правильный" способ расширить функциональность Faker
, что даёт классу:
Прямой доступ ко всем встроенным провайдерам (
address
,person
и тд.)Доступ к ядру генератора через
self.generator
Возможность использовать базовые вспомогательные методы в стиле
random_element
,random_number
и другие
Методы кастомного провайдера
Метод 1 - тип компании
def russian_company_type(self):
types = ['ООО', 'АО', 'ЗАО', 'ИП', 'НКО', 'ГУП']
return self.random_element(types)
Где self.random_element()
- метод Faker для выбора случайного элемента из списка
Метод 2 - код ОКВЭД
def russian_okved(self):
"""Генерация кода ОКВЭД"""
main = str(self.random_int(10, 99))
sub = str(self.random_int(10, 99)) if self.boolean() else ""
return f"{main}.{sub}" if sub else main
Где:
self.random_int()
- генерация случайного целого числаself.boolean()
- случайное True/FalseФормат соответствует "реальным" кодам ОКВЭД (например, "62.01")
Метод 3 - система налогообложения
def russian_tax_system(self):
systems = ['ОСН', 'УСН', 'ЕНВД', 'ЕСХН', 'ПСН']
return self.random_element(systems)
Регистрация и использование
# Создание экземпляра Faker с русской локалью
fake = Faker('ru_RU')
# Добавление кастомного провайдера
fake.add_provider(RussianBusinessProvider)
# Использование методов
print(f"Тип компании: {fake.russian_company_type()}")
print(f"ОКВЭД: {fake.russian_okved()}")
print(f"Система налогообложения: {fake.russian_tax_system()}")
Полная версия провайдера
```python
from faker import Faker
from faker.providers import BaseProvider
import random
class RussianBusinessProvider(BaseProvider):
"""Расширенный провайдер для российского бизнеса"""
# Списки данных для генерации
COMPANY_TYPES = ['ООО', 'АО', 'ЗАО', 'ИП', 'НКО', 'ГУП', 'МУП']
TAX_SYSTEMS = ['ОСН', 'УСН', 'ЕНВД', 'ЕСХН', 'ПСН']
COMPANY_SUFFIXES = ['Групп', 'Холдинг', 'Инвест', 'Трейд', 'Сервис', 'Технологии']
# Словарь популярных ОКВЭД с описаниями
OKVED_CODES = {
'62.01': 'Разработка компьютерного программного обеспечения',
'47.11': 'Торговля розничная в неспециализированных магазинах',
'49.41': 'Деятельность автомобильного грузового транспорта',
'68.20': 'Аренда и управление собственным или арендованным недвижимым имуществом',
'43.21': 'Производство электромонтажных работ'
}
def russian_company_type(self):
"""Тип юридического лица"""
return self.random_element(self.COMPANY_TYPES)
def russian_company_name(self, company_type=None):
"""Генерация названия компании"""
if company_type is None:
company_type = self.russian_company_type()
# База слов для названий
words = ['Север', 'Юг', 'Восток', 'Запад', 'Техно', 'Бизнес', 'Профи',
'Стандарт', 'Элит', 'Глобал', 'Металл', 'Строй', 'Нефть', 'Газ']
name_parts = [
self.random_element(words),
self.random_element(words),
self.random_element(self.COMPANY_SUFFIXES)
]
# Убираем возможные дубликаты
unique_parts = list(dict.fromkeys(name_parts))
company_name = ' '.join(unique_parts)
return f"{company_type} «{company_name}»"
def russian_okved(self, with_description=False):
"""Генерация кода ОКВЭД"""
if with_description:
# Возвращаем случайный ОКВЭД с описанием
code, description = self.random_element(list(self.OKVED_CODES.items()))
return {'code': code, 'description': description}
else:
# Генерация случайного кода
main = str(self.random_int(10, 99))
sub = str(self.random_int(10, 99)) if self.boolean() else ""
return f"{main}.{sub}" if sub else main
def russian_tax_system(self):
"""Система налогообложения"""
return self.random_element(self.TAX_SYSTEMS)
def russian_inn(self, for_individual=False):
"""Генерация ИНН"""
if for_individual:
# ИНН для физического лица (12 цифр)
inn = ''.join([str(self.random_int(0, 9)) for _ in range(12)])
else:
# ИНН для юридического лица (10 цифр)
inn = ''.join([str(self.random_int(0, 9)) for _ in range(10)])
return inn
def russian_kpp(self):
"""Генерация КПП"""
return ''.join([str(self.random_int(0, 9)) for _ in range(9)])
def russian_bank_account(self):
"""Генерация банковского счета"""
return ''.join([str(self.random_int(0, 9)) for _ in range(20)])
def russian_business_address(self):
"""Юридический адрес"""
cities = ['Москва', 'Санкт-Петербург', 'Новосибирск', 'Екатеринбург', 'Казань']
streets = ['ул. Ленина', 'пр. Мира', 'ул. Советская', 'ул. Центральная', 'пр. Победы']
return f"{self.random_element(cities)}, {self.random_element(streets)}, {self.random_int(1, 100)}"
# Регистрация провайдера
fake = Faker('ru_RU')
fake.add_provider(RussianBusinessProvider)
# Демонстрация работы
print("=== ГЕНЕРАЦИЯ ДАННЫХ РОССИЙСКОГО БИЗНЕСА ===")
print()
# Базовая информация
company_type = fake.russian_company_type()
company_name = fake.russian_company_name(company_type)
print(f"Название компании: {company_name}")
print(f"Юридический адрес: {fake.russian_business_address()}")
print()
# Реквизиты
print("Реквизиты:")
print(f"ИНН: {fake.russian_inn()}")
print(f"КПП: {fake.russian_kpp()}")
print(f"ОКВЭД: {fake.russian_okved()}")
print(f"Система налогообложения: {fake.russian_tax_system()}")
print()
# Банковские реквизиты
print("Банковские реквизиты:")
print(f"Расчетный счет: {fake.russian_bank_account()}")
print(f"Банк: {fake.company()}")
print(f"БИК: {fake.random_int(100000000, 999999999)}")
print()
# Детальная информация по ОКВЭД
okved_details = fake.russian_okved(with_description=True)
print(f"Детализация ОКВЭД: {okved_details['code']} - {okved_details['description']}")
```
И, непосредственно пример вывода:
=== ГЕНЕРАЦИЯ ДАННЫХ РОССИЙСКОГО БИЗНЕСА ===
Название компании: ООО «Север Техно Групп»
Юридический адрес: Москва, ул. Ленина, 42
Реквизиты:
ИНН: 7712345678
КПП: 770101001
ОКВЭД: 62.01
Система налогообложения: УСН
Банковские реквизиты:
Расчетный счет: 40702810500000012345
Банк: Иванов и партнеры
БИК: 044525225
Детализация ОКВЭД: 62.01 - Разработка компьютерного программного обеспечения
Заключение
Подведём итоги. Когда вам точно пригодится Faker
?
Тестирование: заполнение базы данных для нагрузочного или интеграционного тестирования
Разработка: создание демо-контента или наполнение макетов интерфейса
Обучение: быстрое развертывание сред для экспериментов с данными
Безопасность: использование реалистичных, но при этом фейковых данных вместо реальных в тестовых средах
На мой взгляд, крайне полезная библиотека под абсолютно разные задачи. Настройка не требует серьезных знаний, использование библиотеки аналогично не сложное. Faker
инструмент, которым пользуюсь часто и, спустя время, он раскрывается словно с новой стороны. Появляются какие-то мысли о кастомных провайдерах, которые могли бы быть полезны в работе/личных проектах. Также, прилагаю ссылку на официальную документацию.
P. S. В моей группе в Телеграмм разбираем практические кейсы: скрипты (Python/Bash/PowerShell), тонкости ОС и инструменты для эффективной работы.