TypedArgs v0.4.0 发布了。大部分接口与 v0.3.x 没有差别,但是少了一个 attribute,所以必须升一个 minor version。这篇博客主要记录我的几个设计失误。
argparse.ArgumentParser
不能被 pickle
TypedArgs 内部是使用 Python 标准库 argparse
实现的。一个标准的 argparse
使用流程如下:
1 | import argparse |
首先,ArgumentParser
支持指定显示的 program 名,那 TypedArgs也应该支持。那一个很自然的想法就是让 parser 成为 class TypedArgs
的一个 attribute,这样解析 arguments 的时候就能自由访问。
1 | from dataclasses import dataclass, field |
但是这带来了一个问题,我并没有意识到 ArgumentParser
是不能被 pickle(序列化)的。虽然平时使用没有问题,但是到了多进程环境(比如 PyTorch 的 DistributedDataParallel
)就会报错。为此。v0.3.x 临时打了一个 patch,在解析完 arguements 之后,将 self.parser = None
。其实这个时候已经造成了 API 变动,minor version 应该 + 1,但是当时思想出了问题,只升了 patch version。当然,没有人会访问 parser,所以理论上问题不大。
v0.4.0 从根本上解决了这个问题,parser 只在解析 arguments 被生成,解析完就回收,不再作为 TypedArgs
上的一个 attribute。
如何让 IDE 正确识别出类型
PyCharm 和 VS Code 对于类型推倒总是有不同的想法。PyCharm 认为 =
后面的才是正确类型,直接忽略了我的 annotation。VS Code 就蠢一点,认为我的 annotation 是对的,但是使用的时候又自作聪明不显示我标注的类型。最后我采用了现在的方案:
1 | foo: str = func() |
这样写,两个 IDE 都能正确推导类型,而且也比较符合常识。
使用 GitHub Action 自动发布到 pypi.org
GitHub 很贴心,GitHub 整个模板都给你弄好了,你只需要去 Settings > Secrets
填两个参数(PYPI_USERNAME
和 PYPI_PASSWORD
)。之后每次 push 带 tag,或者在 GitHub 上创建 release 的时候(创建 release 会创建一个 tag),就会触发这个 GitHub Action,将这个库发布到 pypi.org。