我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python库pydantic怎么用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python库pydantic怎么用

这篇文章主要介绍了python库pydantic怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

    一、简介

    pydantic 库是 python 中用于数据接口定义检查与设置管理的库。

    pydantic 在运行时强制执行类型提示,并在数据无效时提供友好的错误。

    它具有如下优点:

    • 与 IDE/linter 完美搭配,不需要学习新的模式,只是使用类型注解定义类的实例

    • 多用途,BaseSettings 既可以验证请求数据,也可以从环境变量中读取系统设置

    • 快速

    • 可以验证复杂结构

    • 可扩展,可以使用validator装饰器装饰的模型上的方法来扩展验证

    • 数据类集成,除了BaseModel,pydantic还提供了一个dataclass装饰器,它创建带有输入数据解析和验证的普通 Python 数据类。

    二、安装

    pip install pydantic

    要测试 pydantic 是否已编译,请运行:

    import pydanticprint('compiled:', pydantic.compiled)

    支持使用dotenv文件获取配置,需要安装 python-dotenv

    pip install pydantic[dotenv]

    三、常见模型

    pydantic中定义对象都是通过模型的,你可以认为模型就是类型语言中的类型。

    1、BaseModel 基本模型

    from pydantic import BaseModelclass User(BaseModel):    id: int    name = 'Jane Doe'

    上面的例子,定义了一个User模型,继承自BaseModel,有2个字段,id是一个整数并且是必需的,name是一个带有默认值的字符串并且不是必需的

    实例化使用:

    user = User(id='123')

    实例化将执行所有解析和验证,如果有错误则会触发 ValidationError 报错。

    模型具有以下属性:

    • dict() 模型字段和值的字典

    • json() JSON 字符串表示dict()

    • copy() 模型的副本(默认为浅表副本)

    • parse_obj() 使用dict解析数据

    • parse_raw 将str或bytes并将其解析为json,然后将结果传递给parse_obj

    • parse_file 文件路径,读取文件并将内容传递给parse_raw。如果content_type省略,则从文件的扩展名推断

    • from_orm() 从ORM 对象创建模型

    • schema() 返回模式的字典

    • schema_json() 返回该字典的 JSON 字符串表示

    • construct() 允许在没有验证的情况下创建模型

    • __fields_set__ 初始化模型实例时设置的字段名称集

    • __fields__ 模型字段的字典

    • __config__ 模型的配置类

    2、递归模型

    可以使用模型本身作为注释中的类型来定义更复杂的数据结构。

    from typing import Listfrom pydantic import BaseModelclass Foo(BaseModel):    count: int    size: float = Noneclass Bar(BaseModel):    apple = 'x'    banana = 'y'class Spam(BaseModel):    foo: Foo    bars: List[Bar]

    3、GenericModel 通用模型(泛型):

    使用 typing.TypeVar 的实例作为参数,传递给 typing.Generic,然后在继承了pydantic.generics.GenericModel 的模型中使用:

    from typing import Generic, TypeVar, Optional, Listfrom pydantic import BaseModel, validator, ValidationErrorfrom pydantic.generics import GenericModelDataT = TypeVar('DataT')class Error(BaseModel):    code: int    message: strclass DataModel(BaseModel):    numbers: List[int]    people: List[str]class Response(GenericModel, Generic[DataT]):    data: Optional[DataT]    error: Optional[Error]    @validator('error', always=True)    def check_consistency(cls, v, values):        if v is not None and values['data'] is not None:            raise ValueError('must not provide both data and error')        if v is None and values.get('data') is None:            raise ValueError('must provide data or error')        return vdata = DataModel(numbers=[1, 2, 3], people=[])error = Error(code=404, message='Not found')print(Response[int](data=1))#> data=1 error=Noneprint(Response[str](data='value'))#> data='value' error=Noneprint(Response[str](data='value').dict())#> {'data': 'value', 'error': None}print(Response[DataModel](data=data).dict())"""{    'data': {'numbers': [1, 2, 3], 'people': []},    'error': None,}"""print(Response[DataModel](error=error).dict())"""{    'data': None,    'error': {'code': 404, 'message': 'Not found'},}"""try:    Response[int](data='value')except ValidationError as e:    print(e)    """    2 validation errors for Response[int]    data      value is not a valid integer (type=type_error.integer)    error      must provide data or error (type=value_error)    """

    create_model 动态模型

    在某些情况下,直到运行时才知道模型的结构。为此 pydantic 提供了create_model允许动态创建模型的方法。

    from pydantic import BaseModel, create_modelDynamicFoobarModel = create_model('DynamicFoobarModel', foo=(str, ...), bar=123)

    四、常用类型

    • None,type(None)或Literal[None]只允许None值

    • bool 布尔类型

    • int 整数类型

    • float 浮点数类型

    • str 字符串类型

    • bytes 字节类型

    • list 允许list,tuple,set,frozenset,deque, 或生成器并转换为列表

    • tuple 允许list,tuple,set,frozenset,deque, 或生成器并转换为元组

    • dict 字典类型

    • set 允许list,tuple,set,frozenset,deque, 或生成器和转换为集合;

    • frozenset 允许list,tuple,set,frozenset,deque, 或生成器和强制转换为冻结集

    • deque 允许list,tuple,set,frozenset,deque, 或生成器和强制转换为双端队列

    • datetime 的date,datetime,time,timedelta 等日期类型

    • typing 中的 Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union,Callable,Pattern等类型

    • FilePath,文件路径

    • DirectoryPath 目录路径

    • EmailStr 电子邮件地址

    • NameEmail 有效的电子邮件地址或格式

    • PyObject 需要一个字符串并加载可在该虚线路径中导入的 python 对象;

    • Color 颜色类型

    • AnyUrl 任意网址

    • SecretStr、SecretBytes 敏感信息,将被格式化为'**********'或''

    • Json 类型

    • PaymentCardNumber 支付卡类型

    • 约束类型,可以使用con*类型函数限制许多常见类型的值

      • conlist

    • item_type: Type[T]: 列表项的类型

    • min_items: int = None: 列表中的最小项目数

    • max_items: int = None: 列表中的最大项目数

    • conset

    • item_type: Type[T]: 设置项目的类型

    • min_items: int = None: 集合中的最小项目数

    • max_items: int = None: 集合中的最大项目数

    • conint

    • strict: bool = False: 控制类型强制

    • gt: int = None: 强制整数大于设定值

    • ge: int = None: 强制整数大于或等于设定值

    • lt: int = None: 强制整数小于设定值

    • le: int = None: 强制整数小于或等于设定值

    • multiple_of: int = None: 强制整数为设定值的倍数

    • confloat

    • strict: bool = False: 控制类型强制

    • gt: float = None: 强制浮点数大于设定值

    • ge: float = None: 强制 float 大于或等于设定值

    • lt: float = None: 强制浮点数小于设定值

    • le: float = None: 强制 float 小于或等于设定值

    • multiple_of: float = None: 强制 float 为设定值的倍数

    • condecimal

    • gt: Decimal = None: 强制十进制大于设定值

    • ge: Decimal = None: 强制十进制大于或等于设定值

    • lt: Decimal = None: 强制十进制小于设定值

    • le: Decimal = None: 强制十进制小于或等于设定值

    • max_digits: int = None: 小数点内的最大位数。它不包括小数点前的零或尾随的十进制零

    • decimal_places: int = None: 允许的最大小数位数。它不包括尾随十进制零

    • multiple_of: Decimal = None: 强制十进制为设定值的倍数

    • constr

    • strip_whitespace: bool = False: 删除前尾空格

    • to_lower: bool = False: 将所有字符转为小写

    • strict: bool = False: 控制类型强制

    • min_length: int = None: 字符串的最小长度

    • max_length: int = None: 字符串的最大长度

    • curtail_length: int = None: 当字符串长度超过设定值时,将字符串长度缩小到设定值

    • regex: str = None: 正则表达式来验证字符串

    • conbytes

    • strip_whitespace: bool = False: 删除前尾空格

    • to_lower: bool = False: 将所有字符转为小写

    • min_length: int = None: 字节串的最小长度

    • max_length: int = None: 字节串的最大长度

    • 严格类型,您可以使用StrictStr,StrictBytes,StrictInt,StrictFloat,和StrictBool类型,以防止强制兼容类型

    五、验证器

    使用validator装饰器可以实现自定义验证和对象之间的复杂关系。

    from pydantic import BaseModel, ValidationError, validatorclass UserModel(BaseModel):    name: str    username: str    password1: str    password2: str    @validator('name')    def name_must_contain_space(cls, v):        if ' ' not in v:            raise ValueError('must contain a space')        return v.title()    @validator('password2')    def passwords_match(cls, v, values, **kwargs):        if 'password1' in values and v != values['password1']:            raise ValueError('passwords do not match')        return v    @validator('username')    def username_alphanumeric(cls, v):        assert v.isalnum(), 'must be alphanumeric'        return vuser = UserModel(    name='samuel colvin',    username='scolvin',    password1='zxcvbn',    password2='zxcvbn',)print(user)#> name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'try:    UserModel(        name='samuel',        username='scolvin',        password1='zxcvbn',        password2='zxcvbn2',    )except ValidationError as e:    print(e)    """    2 validation errors for UserModel    name      must contain a space (type=value_error)    password2      passwords do not match (type=value_error)    """

    关于验证器的一些注意事项:

    • 验证器是“类方法”,因此它们接收的第一个参数值是UserModel类,而不是UserModel

    • 第二个参数始终是要验证的字段值,可以随意命名

    • 单个验证器可以通过传递多个字段名称来应用于多个字段,也可以通过传递特殊值在所有字段上调用单个验证器'*'

    • 关键字参数pre将导致在其他验证之前调用验证器

    • 通过each_item=True将导致验证器被施加到单独的值(例如List,Dict,Set等),而不是整个对象

    from typing import Listfrom pydantic import BaseModel, ValidationError, validatorclass ParentModel(BaseModel):    names: List[str]class ChildModel(ParentModel):    @validator('names', each_item=True)    def check_names_not_empty(cls, v):        assert v != '', 'Empty strings are not allowed.'        return v# This will NOT raise a ValidationError because the validator was not calledtry:    child = ChildModel(names=['Alice', 'Bob', 'Eve', ''])except ValidationError as e:    print(e)else:    print('No ValidationError caught.')    #> No ValidationError caught.class ChildModel2(ParentModel):    @validator('names')    def check_names_not_empty(cls, v):        for name in v:            assert name != '', 'Empty strings are not allowed.'        return vtry:    child = ChildModel2(names=['Alice', 'Bob', 'Eve', ''])except ValidationError as e:    print(e)    """    1 validation error for ChildModel2    names      Empty strings are not allowed. (type=assertion_error)    """
    • 关键字参数 always 将导致始终验证,出于性能原因,默认情况下,当未提供值时,不会为字段调用验证器。然而,在某些情况下,始终调用验证器可能很有用或需要,例如设置动态默认值。

    • allow_reuse 可以在多个字段/模型上使用相同的验证器

    from pydantic import BaseModel, validatordef normalize(name: str) -> str:    return ' '.join((word.capitalize()) for word in name.split(' '))class Producer(BaseModel):    name: str    # validators    _normalize_name = validator('name', allow_reuse=True)(normalize)class Consumer(BaseModel):    name: str    # validators    _normalize_name = validator('name', allow_reuse=True)(normalize)

    六、配置

    如果您创建一个继承自BaseSettings的模型,模型初始化程序将尝试通过从环境中读取,来确定未作为关键字参数传递的任何字段的值。(如果未设置匹配的环境变量,则仍将使用默认值。)

    这使得很容易:

    • 创建明确定义、类型提示的应用程序配置类

    • 自动从环境变量中读取对配置的修改

    • 在需要的地方手动覆盖初始化程序中的特定设置(例如在单元测试中)

    from typing import Setfrom pydantic import (    BaseModel,    BaseSettings,    PyObject,    RedisDsn,    PostgresDsn,    Field,)class SubModel(BaseModel):    foo = 'bar'    apple = 1class Settings(BaseSettings):    auth_key: str    api_key: str = Field(..., env='my_api_key')    redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1'    pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar'    special_function: PyObject = 'math.cos'    # to override domains:    # export my_prefix_domains='["foo.com", "bar.com"]'    domains: Set[str] = set()    # to override more_settings:    # export my_prefix_more_settings='{"foo": "x", "apple": 1}'    more_settings: SubModel = SubModel()    class Config:        env_prefix = 'my_prefix_'  # defaults to no prefix, i.e. ""        fields = {            'auth_key': {                'env': 'my_auth_key',            },            'redis_dsn': {                'env': ['service_redis_dsn', 'redis_url']            }        }print(Settings().dict())"""{    'auth_key': 'xxx',    'api_key': 'xxx',    'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1',scheme='redis', user='user', password='pass', host='localhost',host_type='int_domain', port='6379', path='/1'),    'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar',scheme='postgres', user='user', password='pass', host='localhost',host_type='int_domain', port='5432', path='/foobar'),    'special_function': <built-in function cos>,    'domains': set(),    'more_settings': {'foo': 'bar', 'apple': 1},}"""

    支持 Dotenv 文件设置变量,pydantic 有两种方式加载它:

    class Settings(BaseSettings):    ...    class Config:        env_file = '.env'        env_file_encoding = 'utf-8'

    或者

    settings=Settings(_env_file='prod.env',_env_file_encoding='utf-8')

    即使使用 dotenv 文件,pydantic 仍会读取环境变量,环境变量将始终优先于从 dotenv 文件加载的值。

    pydantic 支持设置敏感信息文件,同样有2种方式加载:

    class Settings(BaseSettings):    ...    database_password: str    class Config:        secrets_dir = '/var/run'

    或者:

    settings = Settings(_secrets_dir='/var/run')

    即使使用 secrets 目录,pydantic仍会从 dotenv 文件或环境中读取环境变量,dotenv 文件和环境变量将始终优先于从 secrets 目录加载的值。

    七、与 mypy 一起使用

    Pydantic 附带了一个 mypy 插件,向 mypy 添加了许多重要的特定于 pydantic 的功能,以提高其对代码进行类型检查的能力。

    例如以下脚本:

    from datetime import datetimefrom typing import List, Optionalfrom pydantic import BaseModel, NoneStrclass Model(BaseModel):    age: int    first_name = 'John'    last_name: NoneStr = None    signup_ts: Optional[datetime] = None    list_of_ints: List[int]m = Model(age=42, list_of_ints=[1, '2', b'3'])print(m.middle_name)  # not a model field!Model()  # will raise a validation error for age and list_of_ints

    在没有任何特殊配置的情况下,mypy 会捕获其中一个错误:

    13: error: "Model" has no attribute "middle_name"

    启用插件后,它会同时捕获:

    13: error: "Model" has no attribute "middle_name"16: error: Missing named argument "age" for "Model"16: error: Missing named argument "list_of_ints" for "Model"

    要启用该插件,只需添加pydantic.mypy到mypy 配置文件中的插件列表:

    [mypy]plugins = pydantic.mypy

    要更改插件设置的值,请在 mypy 配置文件中创建一个名为 的部分[pydantic-mypy],并为要覆盖的设置添加键值对:

    [mypy]plugins = pydantic.mypyfollow_imports = silentwarn_redundant_casts = Truewarn_unused_ignores = Truedisallow_any_generics = Truecheck_untyped_defs = Trueno_implicit_reexport = True# for strict mypy: (this is the tricky one :-))disallow_untyped_defs = True[pydantic-mypy]init_forbid_extra = Trueinit_typed = Truewarn_required_dynamic_aliases = Truewarn_untyped_fields = True

    感谢你能够认真阅读完这篇文章,希望小编分享的“python库pydantic怎么用”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    python库pydantic怎么用

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    python库pydantic怎么用

    这篇文章主要介绍了python库pydantic怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、简介pydantic 库是 python 中用于数据接口定义检查与设置
    2023-06-29

    怎么使用Python库

    本篇内容介绍了“怎么使用Python库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!数据科学的五个重要步骤包括:获取数据清理数据探索数据构建
    2023-06-16

    Python中random库怎么用

    这篇文章将为大家详细讲解有关Python中random库怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Random库主要包含返回随机数的函数,主要用于普通的随机数生成的程序,如果对随机性有特殊要求,
    2023-06-15

    python openpyxl库怎么使用

    这篇文章主要介绍“python openpyxl库怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“python openpyxl库怎么使用”文章能帮助大家解决问题。openpyxl是一个第三方
    2023-06-27

    python中unittest库怎么使用

    unittest是Python中的一个单元测试框架,用于编写和运行测试。下面是使用unittest库的一些基本方法:导入unittest库:import unittest创建测试类:创建一个继承自unittest.TestCase的测试类。
    2023-10-24

    Python中的tkinter库怎么用

    这篇“Python中的tkinter库怎么用”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“Python中的tkinter库怎么用”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解
    2023-06-28

    Python中Math库怎么使用

    这篇文章主要讲解了“Python中Math库怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中Math库怎么使用”吧!Math 库概述math 库是 Python 提供的内
    2023-07-06

    Python中的Pickle库怎么用

    这篇文章主要为大家展示了“Python中的Pickle库怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中的Pickle库怎么用”这篇文章吧。简介Python 中有个序列化过程叫
    2023-06-28

    Python中requests库怎么使用

    这篇文章主要介绍了Python中requests库怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python中requests库怎么使用文章都会有所收获,下面我们一起来看看吧。一、requests库re
    2023-06-30

    python中zhon库怎么使用

    Zhon是一个Python库,用于提供中文字符集和标点符号的工具。以下是在Python中使用Zhon库的一些常见用法:1. 安装Zhon库:可以使用pip命令来安装Zhon库,命令为:`pip install zhon`2. 导入Zhon库
    2023-08-30

    Python 爬虫库RoboBrowser怎么用

    这篇文章主要介绍“Python 爬虫库RoboBrowser怎么用”,在日常操作中,相信很多人在Python 爬虫库RoboBrowser怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python 爬虫
    2023-06-13

    Python的argparse库怎么使用

    这篇“Python的argparse库怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python的argparse库
    2023-06-27

    python内置库怎么调用

    要调用Python内置库,只需使用import关键字,后跟所需库的名称。例如,要调用math库,可以使用以下语句:import math然后,您可以使用库中的函数和变量。例如,要计算正弦值,可以使用math.sin()函数:impor
    2023-10-24

    python怎么调用函数库

    调用 python 函数库方法:导入函数库(import 语句)使用函数库函数(句点符号后跟函数名称)传递参数(如果需要,在函数名称后面的括号中)如何调用 Python 函数库Python 函数库是预先编写的代码集合,可用于执行各种任务,
    python怎么调用函数库
    2024-05-22

    怎么用Python tkinter库绘图

    这篇文章主要讲解了“怎么用Python tkinter库绘图”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Python tkinter库绘图”吧!一、小房子绘制实例代码:# codin
    2023-06-29

    Python定时库Apscheduler怎么用

    小编给大家分享一下Python定时库Apscheduler怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! 在Python中需要执行定时任务,可以使用Apscheduler。 Apsched
    2023-06-25

    Python的blinker库怎么使用

    本篇内容主要讲解“Python的blinker库怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python的blinker库怎么使用”吧!1、信号信号是一种通知或者说通信的方式,信号分为
    2023-06-29

    python的codecs库怎么使用

    要使用Python的codecs库,需要先导入它:```pythonimport codecs```然后,你可以使用codecs库中的各种函数来处理文件的编码和解码问题。下面是一些常用的codecs库函数的使用示例:1. 打开文件并以指定的
    2023-08-29

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录