使用Poetry实现开发与部署时不同包源配置的最佳实践
我正在开发一个使用自研Python包且依赖Poetry管理的项目:
- 本地开发时,希望安装
--editable模式的本地包版本,方便实时修改代码 - 部署时,希望从私有仓库安装该包的发布版本
我尝试通过两个可选依赖组private和local-private分别配置两种依赖,但遇到了问题:由于包名相同,poetry.lock中仅保留一条记录,导致安装任一依赖组时,my-package都会从同一源拉取。已知Poetry会解析所有可选依赖,想知道是否能为同一包指定不同源,或是我的配置方式有误?
尝试过的配置(失败)
[tool.poetry.group.local-private] optional = true [tool.poetry.group.local-private.dependencies] my-package = {path = "../my-package"} [tool.poetry.group.private] optional = true [tool.poetry.group.private.dependencies] my-package = {version = "^0.2.0", source = "private_repo"} [[tool.poetry.source]] name = "private_repo" url = "https://myprivaterepo.com" priority = "supplemental" [[tool.poetry.source]] name = "PyPI" priority = "primary"
失败原因
Poetry的依赖解析逻辑是全局的——即使依赖分属不同的可选组,同一包名的依赖也会被合并为一条规则。因此poetry.lock中只会保留一组my-package的源信息,导致无论安装哪个依赖组,都会使用同一种安装方式。
临时方案(存在隐患)
我改用pip单独安装本地包,修改后的pyproject.toml如下:
[tool.poetry.group.private] optional = true [tool.poetry.group.private.dependencies] my-package = {version = "^0.2.0", source = "private_repo"} [[tool.poetry.source]] name = "private_repo" url = "https://myprivaterepo.com" priority = "supplemental" [[tool.poetry.source]] name = "PyPI" priority = "primary"
新增private-requirements.txt:
-e ../my-local-package
- 本地安装:先执行
poetry install,再运行pip install -r private-requirements.txt - 部署:执行
poetry install --with private
但该方案的问题是,Poetry无法解析my-local-package的依赖关系,可能引发依赖冲突或版本不一致的隐患。
Poetry支持通过**环境标记(markers)**为同一包配置不同的依赖规则,根据环境变量自动选择对应的依赖源/安装方式,无需维护多个依赖组或额外的requirements文件。
配置方法
修改pyproject.toml,为my-package添加带标记的多规则依赖:
[tool.poetry.dependencies] # 本地开发环境:使用本地路径的editable版本 # 部署环境:使用私有仓库的指定版本 my-package = [ { path = "../my-package", markers = "env LOCAL_DEV = 'true'" }, { version = "^0.2.0", source = "private_repo", markers = "env LOCAL_DEV != 'true'" } ] [[tool.poetry.source]] name = "private_repo" url = "https://myprivaterepo.com" priority = "supplemental" [[tool.poetry.source]] name = "PyPI" priority = "primary"
使用方式
本地开发
设置环境变量后执行安装:
# Linux/macOS export LOCAL_DEV=true poetry install # Windows(PowerShell) $env:LOCAL_DEV = "true" poetry install
此时Poetry会自动选择本地路径的my-package,路径依赖默认以editable模式安装,无需额外加--editable参数。
部署
直接执行安装,无需设置环境变量:
poetry install
Poetry会从私有仓库拉取指定版本的my-package。
注意事项
- 若需跨环境共享lock文件,建议在本地开发环境生成lock文件后,部署环境使用
poetry install --no-root确保环境变量匹配;或分别维护poetry.lock.local和poetry.lock.prod,安装时指定对应文件:poetry install --lock-file poetry.lock.prod。 - 环境变量名称可自定义,只要保持标记规则和实际设置一致即可。
内容的提问来源于stack exchange,提问作者liamtiernan

