当前位置 博文首页 > 东方天宇:为Python项目启用poetry和pyproject.toml

    东方天宇:为Python项目启用poetry和pyproject.toml

    作者:东方天宇 时间:2021-02-06 20:26

    0. 题引

    • 为什么要使用poetry?

      因为想使用pyproject.toml,并通过pyproject.toml进行依赖包管理,目前pip还不支持,所以poetry是首选

    • 为什么要使用pyproject.toml?

      首先pytest、black、isort等常用工具都支持pyproject.toml了,可以实现一个文件完成全项目的配置。
      其次pyproject.toml是PEP中的内容,是将来的方向。试试上,已经有越来越多的开源下项目使用pyproject.toml,我也不能太落后

    扩展阅读:

    pyproject.toml到底是什么东西? (freelycode.com)

    1. Windows安装poetry

    作为Python的一个第三方库。拥有统一、便捷的安装方式:

    pip install poetry
    

    但是这样的安装方式有一些弊端,因为poetry也依赖了很多的其他的包,这些依赖包会同时的一起安装进去。那么这么多的包,尤其不同版本的包,可能会捣乱我们的Python环境。所以我们需要一个方式来进对他进行隔离。

    当然也可以在虚拟环境当中安装poetry,但是这样的话有一个弊端,就是可能需要为每一个虚拟环境分别安装poetry。

    所以为了日后使用起来干净舒服,在这里我放弃了这种最便捷的安装方式,接下来给大家介绍我是如何进行安装的。

    1.1 安装pipx

    pipx会为安装的每一个包自动创建隔离环境,并自动设置环境变量,安装的包能够被执行,非常使用安装那些命令行程序,比如block、httpie、poetry。

    首先在系统级python环境中安装pipx

    pip install pipx
    

    验证安装成功

    λ pipx list
    venvs are in C:\Users\san\.local\pipx\venvs
    apps are exposed on your $PATH at C:\Users\san\.local\bin
    

    1.2 安装 poetry

    C:\Users\san
    λ pipx install poetry 
      installed package poetry 1.1.4, Python 3.9.0
      These apps are now globally available
        - poetry.exe
    done!
    

    安装成功后,使用pipx检查安装效果

    C:\Users\san
    λ pipx list
    venvs are in C:\Users\san\.local\pipx\venvs
    apps are exposed on your $PATH at C:\Users\san\.local\bin
       package poetry 1.1.4, Python 3.9.0
        - poetry.exe
    
    C:\Users\san
    λ poetry
    Poetry version 1.1.4
    
    USAGE
      poetry [-h] [-q] [-v [<...>]] [-V] [--ansi] [--no-ansi] [-n] <command> [<arg1>] ... [<argN>]
    
    ARGUMENTS
      <command>              The command to execute
      <arg>                  The arguments of the command
    
    GLOBAL OPTIONS
      -h (--help)            Display this help message
      .......
    

    自此,poetry就已经安装好了。

    我们是通过pipx安装的poetry,日后也可以通过pipx 更新poetry:

    pipx upgrade poetry
    

    2. 在项目中使用 poetry

    在系统中只有一个poetry就够了,接下来在各个项目中使用即可。

    这里有一个项目APIPractice, 之前是pip +requirement.txt 半手动的方式管理依赖,接下来改为poetry

    2.1 初始化 pyproject.toml

    在项目的根目录,执行poetry是, 并一路回车

    C:\Users\san\github\APIPractice>poetry init
    
    This command will guide you through creating your pyproject.toml config.
    
    Package name [apipractice]:
    Version [0.1.0]:
    Description []:  三木的接口自动化测试练习v1
    Author []:
    License []:
    Compatible Python versions [^3.9]:
    
    Would you like to define your main dependencies interactively? (yes/no) [yes]
    You can specify a package in the following forms:
      - A single name (requests)
      - A name and a constraint (requests@^2.23.0)
      - A git url (git+https://github.com/python-poetry/poetry.git)
      - A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
      - A file path (../my-package/my-package.whl)
      - A directory (../my-package/)
      - A url (https://example.com/packages/my-package-0.1.0.tar.gz)
    
    Search for package to add (or leave blank to continue):
    
    Would you like to define your development dependencies interactively? (yes/no) [yes]
    Search for package to add (or leave blank to continue):
    
    Generated file
    
    [tool.poetry]
    name = "apipractice"
    version = "0.1.0"
    description = "三木的接口自动化测试练习v1"
    authors = ["dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com>"]
    
    [tool.poetry.dependencies]
    python = "^3.9"
    
    [tool.poetry.dev-dependencies]
    
    [build-system]
    requires = ["poetry-core>=1.0.0"]
    build-backend = "poetry.core.masonry.api"
    
    
    Do you confirm generation? (yes/no) [yes]
    

    Do you confirm generation? (yes/no) [yes] 后拿下回车之后,将会在当前目录生成pyproject.toml,内容如下

    [tool.poetry]
    name = "apipractice"
    version = "0.1.0"
    description = "三木的接口自动化测试练习v1"
    authors = []
    
    [tool.poetry.dependencies]
    python = "^3.9"
    
    [tool.poetry.dev-dependencies]
    
    [build-system]
    requires = ["poetry-core>=1.0.0"]
    build-backend = "poetry.core.masonry.api"
    

    2.2 创建项目虚拟环境

    此时peotry使用的还是pipx为它创建的独立虚拟环境

    C:\Users\san\github\APIPractice>poetry env info
    
    Virtualenv
    Python:         3.9.0
    Implementation: CPython
    Path:           NA
    
    System
    Platform: win32
    OS:       nt
    Python:   c:\users\san\.local\pipx\venvs\poetry
    

    接下来要为项目创建项目虚拟环境,以便安装项目的各项依赖

    C:\Users\san\github\APIPractice>poetry env use python
    Creating virtualenv apipractice-gBZexHj9-py3.9 in C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs
    Using virtualenv: C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9
    

    所有由poetry创建虚拟环境会会几种在一个地方,一般情况下,我们不需要直到整个环境的具体路径,

    在项目根目录执行poetry shell 即可进入整个虚拟环境

    C:\Users\san\github\APIPractice>poetry shell
    Spawning shell within C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9
    Microsoft Windows [版本 10.0.19042.746]
    (c) 2020 Microsoft Corporation. 保留所有权利。
    
    C:\Users\san\github\APIPractice>
    

    验证一下

    C:\Users\san\github\APIPractice>pip -V
    pip 20.3.3 from C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9\lib\site-packages\pip (python 3.9)
    

    可以在命令行exit, 会从虚拟环境中退出(回到系统级python)

    C:\Users\san\github\APIPractice>exit
    
    C:\Users\san\github\APIPractice>pip -V
    pip 20.2.3 from c:\users\san\appdata\local\programs\python\python39\lib\site-packages\pip (python 3.9)
    

    2.3 添加新的依赖

    既然要使用poetry来进行依赖包的管理,那我们在后面也会的避免使用pip ,

    添加依赖的命令

    • poetry add <pakge_name>

    但是有些不好用

    C:\Users\san\github\APIPractice>poetry add fastapi[all]
    Using version ^0.63.0 for fastapi
    
    Updating dependencies
    Resolving dependencies...
    
      ConnectionError
    
      HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/f4/2b/078a9771ae4b67e36b0c2a973df845260833a4eb088b81c84b738509b4c4/aiofiles-0.5.0-py3-none-any.whl (Caused by NewConnectionError('
    <urllib3.connection.HTTPSConnection object at 0x0000021BE6355250>: Failed to establish a new connection: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。'))
    
      at c:\users\san\.local\pipx\venvs\poetry\lib\site-packages\requests\adapters.py:516 in send
          512│             if isinstance(e.reason, _SSLError):
          513│                 # This branch is for urllib3 v1.22 and later.
          514│                 raise SSLError(e, request=request)
          515│
        → 516│             raise ConnectionError(e, request=request)
          517│
          518│         except ClosedPoolError as e:
          519│             raise ConnectionError(e, request=request)
          520│
    
    

    从错误提示来看,poetry没有使用pip的配置,从其他源下载文件,所有出现了网络错误。

    这是poetry已经被吐槽很多次的问题了。。。

    解决办法:

    pyproject.toml 文件中添加如下内容:

    [[tool.poetry.source]]
    name = "aliyun"
    url = "https://mirrors.aliyun.com/pypi/simple"
    

    接下来他会花比较久的时间去分析fastpi的依赖关系,以及依赖包的依赖关系。最终会生成一个大约800行内容的poetry.lock文件, 并且修改pyproject.toml

    [tool.poetry.dependencies]
    python = "^3.9"
    fastapi = {extras = ["all"], version = "^0.63.0"}
    
    

    自此,依赖安装成功。

    为了以后避免出现其他的状况,本项目中尽量不要在用pip做任何事情。。。把pip暂时忘记吧

    2.4 添加开发依赖

    默认情况下,poetry所添加的依赖是在运行这个项目时所需要的一些包,但是在我们开发的时候,其实还需要一些工具进行配合。

    比如说测试框架pytest,如果单纯是为了启动这个项目的话,其实是不需要进行安装的。

    所以把这些在运行时不需要安装,在开发时所需要安装的依赖我们称之为开发依赖。

    安装开发依赖的方式很简单,就是加一个-D参数

    C:\Users\san\github\APIPractice>poetry add -D pytest
    Using version ^6.2.2 for pytest
    
    Updating dependencies
    Resolving dependencies...
    
    Writing lock file
    
    Package operations: 9 installs, 0 updates, 0 removals
    
      ? Installing pyparsing (2.4.7)
      ? Installing atomicwrites (1.4.0)
      ? Installing attrs (20.3.0)
      ? Installing iniconfig (1.1.1)
      ? Installing packaging (20.9)
      ? Installing py (1.10.0)
      ? Installing pluggy (0.13.1)
      ? Installing toml (0.10.2)
      ? Installing pytest (6.2.2)
    

    然后我们运行pytest执行测试。

    因为pytest是被安装在虚拟环境当中,所以我们执行拍pytest有两种方式:

    • 第一种:先进入虚拟环境,然后执行pytest

      C:\Users\san\github\APIPractice>poetry shell
      Spawning shell within C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9
      Microsoft Windows [版本 10.0.19042.746]
      (c) 2020 Microsoft Corporation. 保留所有权利。
      
      C:\Users\san\github\APIPractice>pytest
      ==================== test session starts =====================
      platform win32 -- Python 3.9.0, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
      rootdir: C:\Users\san\github\APIPractice
      collected 29 items                                                                                                   
      
      tests\test_default.py ....                   [ 13%]
      tests\test_encrypt.py ...                    [ 24%]
      tests\test_file.py .......                   [ 48%]
      tests\test_login.py ......                   [ 68%]
      tests\test_token.py .........                 [100%]
      
      =============== 29 passed in 1.16s ===============
      
    • 第二种:让pytest在虚拟环境中执行

      C:\Users\san\github\APIPractice>poetry run pytest
      ==================== test session starts =====================
      platform win32 -- Python 3.9.0, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
      rootdir: C:\Users\san\github\APIPractice
      collected 29 items                                                                                                   
      
      tests\test_default.py ....                   [ 13%]
      tests\test_encrypt.py ...                    [ 24%]
      tests\test_file.py .......                   [ 48%]
      tests\test_login.py ......                   [ 68%]
      tests\test_token.py .........                 [100%]
      
      =============== 29 passed in 1.13s ===============
      

    3. 总结

    现在新的项目已经使用poetry和pyproject.toml来进行管理了。

    回顾发现,poetry在开始做了2件事:

    1. 初始化pyproject.toml
    2. 创建虚拟环境

    之后,主要负责:

    • 管理依赖

    • 切换虚拟环境

    使用poetry目前有2个不爽:

    • 依赖分析较慢,安装包要等待很久
    • 不使用pip配置文件访问pypi源,需要指定在pyproject.toml文件中 (会进入git)
    bk