Nixpkgs中如何让Python包duckdb使用Overlay修改后的DuckDB?
问题:Python版DuckDB未使用Overlay修改后的版本
我使用如下Flake配置:
{ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; overlays = [ (final: prev: { duckdb = prev.duckdb.overrideDerivation(old: { cmakeFlags = old.cmakeFlags ++ ["-DSKIP_EXTENSIONS=jemalloc"]; }); }) ]; }; python = pkgs.python311; buildInputs = with pkgs; [ (python.withPackages (ps: with ps; [ duckdb ])) duckdb ]; in with pkgs; { devShells.default = mkShell { inherit buildInputs; }; } ); }
我成功构建了不含jemalloc的DuckDB,通过命令行测试:
echo "SELECT installed FROM duckdb_extensions() WHERE extension_name='jemalloc';" | duckdb
返回false,符合预期。但Python包python3Packages.duckdb仍使用未修改前的DuckDB版本,执行以下测试代码失败:
import duckdb assert not duckdb.connect().execute("SELECT installed FROM duckdb_extensions() WHERE extension_name='jemalloc';").fetchone()[0]
我本以为Overlay会作用于整个pkgs集合,使pkgs.python311.duckdb使用修改后的DuckDB,但实际并非如此。请问正确的实现方式是什么?我对Overlay的理解存在哪些误区?
误区分析
你对Overlay的核心误区在于:Python包集合(比如python311.pkgs)是独立于顶层pkgs的衍生集合,顶层Overlay不会自动渗透到Python的包集合中。
具体来说,pkgs.python311是一个带有自身包集合的Python环境,它的duckdb包是基于Python自身的依赖解析逻辑构建的,默认会使用Python包集合里引用的原始DuckDB,而非顶层pkgs中被Overlay修改后的版本。
正确实现方式
要让Python版DuckDB使用修改后的底层DuckDB,需要在Overlay中同时修改Python包集合里的duckdb,让它依赖顶层修改后的duckdb。修改后的Flake配置如下:
{ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; overlays = [ (final: prev: { # 1. 修改顶层的DuckDB duckdb = prev.duckdb.overrideDerivation(old: { cmakeFlags = old.cmakeFlags ++ ["-DSKIP_EXTENSIONS=jemalloc"]; }); # 2. 修改Python包集合中的duckdb,让它依赖修改后的顶层duckdb python311 = prev.python311.override { packageOverrides = pythonFinal: pythonPrev: { duckdb = pythonPrev.duckdb.overridePythonAttrs(old: { propagatedBuildInputs = old.propagatedBuildInputs ++ [final.duckdb]; # 强制重新构建,确保链接到新的DuckDB doCheck = false; # 可选,若测试用例依赖jemalloc可临时关闭 }); }; }; }) ]; }; python = pkgs.python311; buildInputs = with pkgs; [ (python.withPackages (ps: [ps.duckdb])) duckdb ]; in with pkgs; { devShells.default = mkShell { inherit buildInputs; }; } ); }
关键修改点:
- 在顶层Overlay中,通过
python311.override给Python环境添加packageOverrides,专门修改Python包集合里的duckdb。 - 使用
overridePythonAttrs覆盖Python版DuckDB的属性,让它依赖顶层修改后的duckdb,确保编译/链接时使用不含jemalloc的版本。 - 可选关闭
doCheck:如果Python版DuckDB的测试用例依赖jemalloc存在,可能需要临时关闭测试以构建成功。
修改后重新进入devShell,运行Python测试代码即可验证断言通过。
内容的提问来源于stack exchange,提问作者2e0byo
相关产品推荐
相关产品推荐

