术语

分发工具(打包)

resource 访问

importlib_resources

获取 data file 路径

1
2
3
4
5
from importlib_resources import files, as_file

source = files(email.tests.data).joinpath('message.eml')
with as_file(source) as eml:
    third_party_api_requiring_file_system_path(eml)
  • files 获取 package 路径

    • 对于 压缩包,通过临时解压缩得到路径
  • as_file 创建 context 对象,便于回收数据

过时用法

  • 制作 context 对象

    • open_text
    • open_binary
    • path
  • 读取数据

    • read_text
    • read_binary
  • 路径

    • path
  • data file 列表

    • contents(package)
  • 判断

    • is_resource(package, name)

pkg_resources

注意:

  • 不是 setuptools 的子模块
  • 是 setuptools 的项目的子项目

好处:

  • 即使整个包是放在压缩文件中的,也可访问

    • 这种 os.path 路径操作就无法访问了

data 文件

获取文件名(路径)

pkg_resources.resource_filename

1
2
3
import pkg_resources

filename = pkg_resources.resource_filename('package_name', 'sub_package/folder/to/filename.txt')
获取文件内容

pkg_resources.resource_string

  • 类似 open('filename.txt'), 返回 bytes 类似数据
1
2
3
4
5
6
7
from pkg_resources import resource_string as resource_bytes

# data 也是包 package 时
eml = resource_bytes('email.tests.data', 'message.eml').decode('utf-8')

# data 不是包,用法
eml = resource_bytes('email.tests', 'data/message.eml').decode('utf-8')
  • 限制

    • 在 email, email/tests, email/tests/data 文件夹下都要有 __init__.py 文件

      • 其中 data 下的 __init__.py 是不必要的,我们不是作为包文件,只是用来放 data files
    • 即,需要创建不必要的 python sub packages

包管理工具

工具联用

poetry 和 pyenv 联用

  1. 方法一

    1. pyenv install 安装 python 版本
    2. pyenv local 切换项目 python 版本
    3. poetry install 自动关联 python 版本
    4. poetry shell 切换到 virtualenv
  2. 方法二

    • poetry env use /full/path/to/python guanlian

      • 使用 pyenv 安装的具体版本
      • poetry env use ~/.pyenv/versions/<python-version>/bin/python
    • poetry shell 切换到 virtualenv

conda 和 pyenv 分别单独安装使用

  • 不要同时切换 pyenv 和 conda activate
  • 解决方法

    • 单独使用两者,退出一个再启用另一个
    • 避免交叉使用
  • pyenv

    • 激活:pyenv global py38
    • 退出:pyenv global system
  • conda

    • 激活:conda activate conda38
    • 退出:conda deactivate conda38

C 扩展打包

Cython

  • 例子 setup.py

    1
    2
    3
    4
    5
    6
    7
    8
    
      from setuptools import setup
      from Cython.Build import cythonize
    
      setup(
          name='Hello world app',
          ext_modules=cythonize("hello.pyx"),
          zip_safe=False,
      )
  • 执行 python setup.py build_ext --inplace

poetry

打包工具

  • setuptools

    • 古老
  • poetry

    • 包管理一体
  • flit

    • 简单
  • pdm

测试工具

  • pytest
  • tox

文件布局 layout

参考:

  1. src 布局

    • 代码存放到 src 文件夹中
  2. flat layout

    • 代码直接放到 project-root 中