首页Python【Python计算生态】M...

【Python计算生态】Mimesis——高性能伪数据生成库

Python受欢迎的原因之一就是其计算生态丰富,据不完全统计,Python 目前为止有约13万+的第三方库。

本系列将会陆续整理分享一些有趣、有用的第三方库。

文章配套代码获取有以下两种途径:
  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1FSGLd7aI_UQlCQuovVHc_Q?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/Python_Ecosystem





01
简介

mimesis是一个高性能伪数据生成库,能够快速生成各种类型的假数据:
  • 多语言:支持 46 种不同的语言环境。
  • 可扩展性:支持自定义数据提供者和自定义字段处理器。
  • 易用性:设计简单,文档清晰,便于数据生成。
  • 性能:被认为是 Python 中最快的假数据生成器。
  • 数据多样性:包含多种数据提供者,适用于不同的使用场景。
  • 基于模式的生成器:提供基于模式的数据生成器,可以轻松生成任何复杂度的数据。
  • 直观性:编辑器支持良好,完全类型化,几乎处处支持自动补全。
直接使用pip安装:
pip install mimesis
GitHub页面:
https://github.com/lk-geimfari/mimesis

02
基本使用

使用 Mimesis 的典型过程包括导入所需的提供者、语言环境以及枚举(如果需要)。接下来,创建提供者的实例,并调用所需的方法并传入适当的参数。


# Person 类是 mimesis 库中用于生成个人信息的类
from mimesis import Person
# Locale 类包含了各种语言和地区的枚举值,用于指定生成数据的语言和地区
from mimesis.locales import Locale
# Gender 类是一个枚举类,包含了男性和女性两种性别选项
from mimesis.enums import Gender

# 创建Person类的实例,传入Locale.EN作为参数,表示希望生成的数据使用英语语言环境
person = Person(Locale.EN)

# 生成了一个随机的女性全名
print(person.full_name(gender=Gender.FEMALE))
# 输出:'Antonetta Garrison'

# 生成了一个随机的男性全名
print(person.full_name(gender=Gender.MALE))
# 输出:'Jordon Hall'
  • Generic() 类:

如果只需要访问某个特定类提供的数据,导入单独的类提供者可能是有用的。然而,如果需要访问更广泛的数据,建议使用 Generic() 类,将能够访问库中所有可用提供者提供的数据。

在 mimesis 库中,Generic 类是一个综合性的类,它整合了多种数据提供者(providers),提供了一种便捷的方式来访问不同类型的模拟数据生成功能,而无需分别初始化和管理每个提供者。

# 导入 Generic 类
from mimesis import Generic
from mimesis.locales import Locale

# 创建一个 Generic 类的实例,并指定使用中文(Locale.ZH)作为语言环境
generic = Generic(locale=Locale.ZH)

# 生成一个中文姓名
print(generic.person.full_name())
# 输出:思宇 孙

# 生成一个中郭城市名
print(generic.address.city())
# 输出:大庆市

# 生成一个中文银行名
print(generic.finance.bank())
# 输出:Bank of Jinzhou Co., Ltd.
03
语言环境

Mimesis 当前支持 42 种不同的语言环境。

在创建提供者(providers)时指定语言环境,它们将返回与该语言环境相关联的语言或国家的数据,所有提供者的默认语言环境是英语(美国)(Locale.EN)。


from mimesis import Address
from mimesis.locales import Locale

# 通过 locale 参数指定使用中文地区(Locale.ZH)
zh = Address(locale=Locale.ZH)
# 通过 locale 参数指定使用俄语地区(Locale.RU)
ru = Address(locale=Locale.RU)

print(zh.region())
# 输出:江苏省
print(zh.address())
# 输出:西塞八条1055号

print(ru.region())
# 输出:Хабаровский край
print(ru.address())
# 输出:ул. Автомоторная 561
  • 临时覆盖语言环境:

有时只需要从其他语言环境中获取一些数据,而为此创建一个实例并不是一个好选择。因此,可以使用临时覆盖提供者实例当前语言环境的方式:


from mimesis import Address
from mimesis.locales import Locale

address = Address(locale=Locale.EN)
print(address.region())
# 输出:North Carolina

with address.override_locale(Locale.ZH):
    print(address.region())
    # 输出:西藏自治区

print(address.region())
# 输出:Kansas

也可以与 Generic() 类一起使用:


from mimesis import Generic
from mimesis.locales import Locale

generic = Generic(locale=Locale.EN)
print(generic.text.word())
# 输出:price

with generic.text.override_locale(Locale.ZH):
    print(generic.text.word())
    # 输出:比重

print(generic.text.word())
# 输出:anarchist
04
数据提供者

Mimesis支持超过二十种不同的数据提供者(providers),可以生成与食品、人员、交通、地址等相关的数据。具体内容请参阅API文档:

https://mimesis.name/latest/api.html#api-reference
  • 提供者类型:

提供者(providers)分为两种类型:

依赖语言环境的提供者:这些提供者提供特定于某个语言环境/国家的数据,如果没有为依赖语言环境的提供者指定语言环境,将使用默认语言环境(即 Locale.EN)。

不依赖语言环境的提供者:这些提供者提供通用数据,适用于所有国家,不依赖语言环境的提供者不需要指定语言环境,如果尝试为不依赖语言环境的提供者指定语言环境,将会抛出异常。


from mimesis import Person,Code
from mimesis.locales import Locale

# 依赖语言环境的提供者
person = Person(locale=Locale.EN)
print(person.name())
# 输出:Sammie

# 不依赖语言环境的提供者
code = Code()
print(code.issn()) # 国际刊号
# 输出:1296-0277
  • 内置提供者:

通常,在只有一种官方语言的国家,会有一些特定类型的数据是独有的。例如,在巴西(Locale.PT_BR)中使用“CPF”,而在美国(Locale.EN)中使用“SSN

Mimesis 通过将具有本地特定数据的类提供者分离到一个特殊的子包(mimesis.builtins)中,来解决上述问题,从而确保了特定区域的提供者不会给其他区域的提供者带来不便。这种方法有助于维护所有语言及其对象的通用类结构。

使用时,可以直接使用内置类,也可以将内置类添加到 Generic 对象使用。另外,可以通过更改 Meta.name 属性的值或者通过继承类并覆盖提供者的 Meta 类的 _name_ 属性,来修改内置提供者的默认名称。


from mimesis import Generic
from mimesis.locales import Locale
from mimesis.builtins import BrazilSpecProvider

generic = Generic(locale=Locale.PT_BR)
generic.add_provider(BrazilSpecProvider)
print(generic.brazil_provider.cpf())
# 输出:098.772.113-51

# 修改内置提供者的默认名称
BrazilSpecProvider.Meta.name = 'brasil'
generic.add_provider(BrazilSpecProvider)
print(generic.brasil.cpf())
# 输出:204.929.515-43
  • 自定义提供者:

Mimesis 提供了广泛的数据支持,足以满足大多数用例。如果,希望创建更具体数据的自定义提供者,可以通过定义自定义提供者类的方式实现。

需要注意的是,所有提供者(providers)都必须是 BaseProvider 的子类,以确保只使用单个 Random 对象实例。如果尝试添加一个未继承自 BaseProvider 的提供者,将会收到一个 TypeError 异常。

另外,Meta 类中的 name 属性是指通过类名访问用户自定义提供者方法时使用的名称。默认情况下,使用类名(cls.__name__)的小写形式。


from mimesis import Generic
from mimesis.locales import Locale
# BaseProvider 类是 mimesis 库中所有数据提供者的基类,自定义提供者通常需要继承该类
from mimesis.providers.base import BaseProvider

# 定义一个自定义的数据提供者类 SomeProvider,继承自 BaseProvider 类
class SomeProvider(BaseProvider):
    # 在类内部定义一个 Meta 类,Meta 类用于设置该提供者的元信息
    class Meta:
        name = "some_provider"

    # 定义一个静态方法 hello
    @staticmethod
    def hello():
        return"Hello!"

# 定义另一个自定义的数据提供者类 Another,同样继承自 BaseProvider 类
class Another(BaseProvider):
    # 定义类的构造函数,接收两个参数:seed 和 message
    def __init__(self, seed, message: str):
        super().__init__(seed=seed)
        self.message = message

    # 定义一个实例方法 bye
    def bye(self):
        return self.message

# 创建一个 Generic 类的实例,指定使用默认的语言环境(Locale.DEFAULT)。
generic = Generic(locale=Locale.DEFAULT)

# 向 generic 实例中添加自定义的数据提供者 SomeProvider
# 也可以使用 += 运算符来添加提供者,效果相同
generic.add_provider(SomeProvider)  # 或 generic += SomeProvider
generic.add_provider(Another, message="Bye!")


print(generic.some_provider.hello())
# 输出:'Hello!'
print(generic.another.bye())
# 输出:'Bye!'
  • 自定义数据提供者:

要创建自己的数据提供者并将数据存储在 JSON 文件中,可以按照以下步骤操作:

首先,创建一个目录来存储数据,结构如下:

为了确保提供者支持所需的语言环境,每个自定义数据目录(datadir)都必须包含一个以语言环境名称命名的目录。


custom_datadir/
├── de
│   └── file_name.json
├── en
│   └── file_name.json
└── ru
    └── file_name.json

接下来,需要在文件中填充相关数据。例如:


{
  "key": [
    "value1",
    "value2",
    "value3"
  ]
}

之后,需要创建一个继承自 BaseDataProvider 的类,其中Meta 类是必需的,并且必须包含以下属性:

  • name:提供者的名称,使用小写字母。

  • datafile:数据文件的名称。

  • datadir:数据目录的路径(必须是 Path 的实例)。


from pathlib import Path
import os
from mimesis import BaseDataProvider
from mimesis.locales import Locale

class CustomDataProvider(BaseDataProvider):
    class Meta:
        name = 'custom_provider'
        datafile = 'file_name.json'
        # __file__ 是一个特殊变量,仅在脚本运行时由 Python 解释器自动定义,表示当前脚本的文件路径
        # 在交互式环境(如 Jupyter Notebook 或 Python REPL)中不可用
        # datadir = Path(__file__).parent / 'custom_datadir'
        # 使用 os.getcwd() 获取当前工作目录,然后拼接路径
        datadir = Path(os.getcwd()) / 'custom_datadir'# 动态获取路径

    def my_method(self):
        return self.random.choice(self._extract(["key"]))

cdp = CustomDataProvider(Locale.EN)
print(cdp.my_method())
# 输出:'value3'
05
结构化数据生成

Mimesis 提供了强大的结构化数据生成功能,通过 FieldFieldset 和 Schema 类,可以灵活地生成各种结构化的假数据。

  • Field:用于为给定字段名称生成单个值。

  • Fieldset:用于为给定字段名称生成一组值。

  • Schema:使用定义好的模式生成结构化数据。

其中,Field 和 Fieldset 的实例是可调用对象,接受以下参数:

  • 第一个参数为方法名称(name)。

  • 第二个参数为键函数(key),可选。

  • 其余参数为传递给方法的 **kwargs

  • 字段名称指定方式:
字段名称有以下两种指定方式:
显式方式:通过 provider.method 的形式指定字段名称,避免方法名称冲突。
隐式方式:仅指定方法名称,不引用提供者的名称。此时,Mimesis 将调用第一个注册的自定义字段处理器(如果存在),或者调用第一个具有该方法名称的提供者。需要注意的是,如果注册了一个与提供者方法名称匹配的自定义字段处理器,由于优先级更高,自定义字段处理器将被调用,而不是提供者的方法。

from mimesis import Field
field = Field()
# 显式方法
print(field("person.username", key=str.upper))
# 输出:UPGRADING_2087

# 隐式方法
print(field("username", key=str.upper))
# 输出:VERMONT_1998
  • 生成单个值和一组值:
单个值:要为特定字段生成单个值,需要实例化 Field 类,访问所有可用提供者的方法。
一组值:通过 Fieldset 实例调用方法生成,并通过关键字参数 i 指定生成的数量,如果未指定将使用合理的默认值10。

from mimesis import Field, Locale, Fieldset

# 生成单个值
field = Field(locale=Locale.EN)
print(field("name"))
# 输出:Annalee

# 生成一组值
fieldset = Fieldset(locale=Locale.EN)
print(fieldset("name", i=3))
# 输出:['Shona', 'Colby', 'Jeffery']
  • 模式定义:

使用 Schema 类和模式定义(通过 lambda 函数动态生成)来生成结构化数据。


from mimesis import Field, Fieldset, Schema
from mimesis.enums import Gender, TimestampFormat
from mimesis.locales import Locale

field = Field(Locale.EN, seed=0xff)
fieldset = Fieldset(Locale.EN, seed=0xff)

# 示例模式定义
# 模式必须包装在一个可调用对象中,以确保它动态地被评估,而不是仅在第一次调用时生成相同的数据
schema_definition = lambda: {
    "pk": field("increment"),
    "uid": field("uuid"),
    "name": field("text.word"),
    "version": field("version"),
    "timestamp": field("timestamp", fmt=TimestampFormat.POSIX),
    "owner": {
        "email": field("person.email", domains=["mimesis.name"]),
        "creator": field("full_name", gender=Gender.FEMALE),
    },
    "apiKeys": fieldset("token_hex", key=lambda s: s[:16], i=3),
}

# 创建 Schema 的实例,并通过调用 create() 方法生成数据
schema = Schema(schema=schema_definition, iterations=3)
schema.create()
  • 字段别名:
要使用字段别名,需要实例化 Field 或 Fieldset,然后更新其 aliases 属性(一个普通的字典),将别名与字段名称关联起来。

from mimesis import Field, Locale

field = Field(Locale.ZH)

# 键是别名,值是与别名关联的字段名称(两者都应是字符串)。
field.aliases.update({
    '📧''email',
    '📞''person.telephone',
    '🍆''vegetable',
})

# 使用别名代替标准字段名称
print(field('📧', domains=['@gmail.com']))
# 输出:specified1895@gmail.com
print(field('📞'))
# 输出:+86 105-45957080
print(field('🍆'))
# 输出:芥菜

当不再需要别名时,可以像操作普通字典键一样逐个删除它们,或者一次性清除所有别名:


field.aliases.pop('📧')

# 清除所有别名
field.aliases.clear()
  • 键函数与后处理:

可以选择将键函数应用于 Field 或 Fieldset 实例返回的结果。为此,只需将一个返回最终结果的可调用对象作为 key 参数传递。

以下是一个示例:


from mimesis import Field, Fieldset, Locale
from mimesis.keys import maybe

field = Field(Locale.EN)

# 使用 key 参数对生成的结果进行后处理
print(field("name", key=str.upper))
# 输出:ELENI

# 内置键函数 maybe():以一定概率生成特定值(如 None 或 'N/A')
fieldset = Fieldset(Locale.EN, i=5)
print(fieldset("email", key=maybe(None, probability=0.6)))
# 输出:[None, 'sword1981@live.com', None, None, None]
06
随机数生成器与种子

  • 随机数生成器:

Mimesis 库中的所有数据提供者都是 BaseProvider 类的子类,该类有一个 random 属性。该属性是 random 模块中 Random 类的实例。如果正在创建自己的数据提供者,应使用该 random 属性来访问随机数生成器。


from mimesis import BaseProvider

class MyProvider(BaseProvider):
    class Meta:
        name = 'my_provider'

    def my_method(self):
        return self.random.randint(0, 100)

my_provider = MyProvider()
my_provider.my_method()
# 输出:66
  • 设置种子:

要使用种子生成数据,只需将参数 seed(可以是 intstrbytes 或 bytearray)传递给数据提供者:


from mimesis import Person, Locale

# 设置种子
person = Person(locale=Locale.TR, seed=0xFF)
person.full_name()
# 输出:'Giray Tekand'
  • 重新设置种子:

要重新设置随机数生成器的种子,可以使用 BaseProvider 类的 reseed() 方法:


from mimesis import Person, Locale

person = Person(Locale.EN, seed='Wow.')
print(person.name())
# 输出:'Fausto'

# 重新设置种子
person.reseed('111')
print(person.name())
# 输出:'Billy'

如果希望所有数据提供者使用相同的种子,那么使用 Generic() 是一个好选择:


from mimesis import Generic, Locale

generic = Generic(Locale.EN, seed='123')
print(generic.person.name())
# 输出:Julio
print(generic.datetime.date())
# 输出:2023-02-11
print(generic.text.word())
# 输出:raise
  • 加权选择:

如果希望生成具有特定出现概率的数据,可以使用 weighted_choice 方法来实现加权随机选择。

例如,假设希望生成随机的男性和女性全名,但生成女性名字的概率更高。


from mimesis import Person, Locale, Gender

person = Person(Locale.EN)

for _ in range(10):
    full_name = person.full_name(
        # person.random 是 Person 实例的随机数生成器对象,提供了各种随机选择的方法
        # weighted_choice 是该随机数生成器对象的方法,用于根据权重随机选择元素
        gender=person.random.weighted_choice(
            choices={
                Gender.MALE: 0.2,
                Gender.FEMALE: 0.8,
            }
        ),
    )
    print(full_name)

# 输出:Wilton Bass
#      Milda Middleton
#      Torie Parker
#      Kathey Harrison
#      Saran Willis
#      Reinaldo Fulton
#      Carlos Lucas
#      Jeff Sullivan
#      Shakita Levy
#      Shalon Poole
  • 全局种子:
可以为所有数据提供者设置一个全局种子,并在不显式传递种子的情况下使用它。

from mimesis import random
from mimesis import Person, Locale

# 设置全局种子
random.global_seed = 0xFF

person = Person(Locale.EN)
person.full_name()
# 输出:'Karl Munoz'


更多内容可以前往官方文档查看:

https://mimesis.name/master/

本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments