HydroOJ 从入门到入土(10) 配置 nix 支配下的 Python 环境

发布时间 2023-12-22 00:42:51作者: Bowen404

官网已经更新了在线生成数据的功能, 方便不少, 如果能用我习惯用的 cyaron 数据生成器就好了. 但 nix 作为 Hydro 的安全沙箱, 隔离性做的太好, 以至于跟 Python 这种喜爱全局安装包的编译器天生八字不合, 用 nix 安装 Python 包, 大坑套小坑, 这里记录一下解决的几种方法.

1. 基本方法

参考官网faq: 15. 在沙箱中引入 Python 包, 基本思想是先用 nix-env 安装一个包, 如果不行的话, 就尝试找出这个包的所在位置, 然后手动添加到运行环境中. 可以用, 但是比较麻烦.

而且, 我在尝试安装cyaron的时候, 发现无法通过 nix-shell -p xxx 的方法加载 cyaron, 试了好多都出错, 不知道中间该填什么.

最后还是用 ls -alh /nix/store/ | grep cyaron 手动筛出了cyaron的真实地址.

2. 半自动方法

以下以 Python3.11 为例.

根据第一种方法, 会发现有的包, 比如numpy, 装完就可以直接用, 但是有的就不行, 比如pandas.

经过进一步探究, 发现使用nix-env -iA nixpkgs.python311Packages.xxxxx这种方式安装的包, 是直接将包装到/nix/store/里, 然后再把包中的xxx/lib/python3.11/site-packages里边所有的库写一个软链接到 ~/.nix-profile/lib/python3.11/site-packages 这个位置, 所以 numpypandas 其实装完都在这个环境里.

但用nix-env -iA安装的时候, 自动安装的那些依赖项却并不会被加进 nix 的安装列表(nix-env q查不到), 所以当然也不会被加进这个路径!

这也直接导致了 pandascyaron安装完无法使用, 只有像numpy这种单一个包的才能直接用.

明确了这个思路之后, 我就看一下某个包的依赖多不多, 如果不多的话, 就手动安装所有依赖项, 避免之后处理 path.

经过一番尝试, 幸好依赖都不多, 我成功安装了 3 个库, 并确定安装顺序如下:

2.1 numpy

一个包, 没啥依赖项, 直接装了, 重启沙箱就能用:

nix-env -iA nixpkgs.python311Packages.numpy

2.2 pandas

依赖有 5 个, 其中一个是numpy, 所以需要要在 pandas 之前安装numpy.

nix-env -iA nixpkgs.python311Packages.six
nix-env -iA nixpkgs.python311Packages.tzdata
nix-env -iA nixpkgs.python311Packages.pytz
nix-env -iA nixpkgs.python311Packages.dateutil
nix-env -iA nixpkgs.python311Packages.numpy
nix-env -iA nixpkgs.python311Packages.pandas

2.3 cyaron

这个搞了很久, 因为安装 cyaron 依赖 xeger, 但是这个包 nix 官方没找到. 这俩可能都不是 nix 官方 channel, 最后想起来 Hydro 的repo 里好像有个 nix 什么的, 果然在这里.

找到就好办了, 顺序如下:

nix-env -iA hydro.xeger
nix-env -iA hydro.cyaron

按照以上顺序安装, 可以不需要设置 path. 重启沙箱即可使用.

2.4 装完记得重启沙箱

pm2 restart hydro-sandbox

2.5 其他库

包很多, 想装什么, 可以在 pypi 上查好依赖, 然后手动安装. 如果装错顺序导致导入时报依赖错误, 就删掉, 换个顺序重装.

注意, 在nix-env -iA xxx的时候, 最上边会显示几行要装的东西, 这个就是依赖项, 可以记下来.

3. 其他操作

更新 channel

nix-channel --update 

清除不用的软件包(垃圾回收)

注意, nix-env -e 只会删除指定包, 但是仍有可能会留下一些 old generation, 所以过段时间会变得巨大, 需要使用垃圾回收清理.

nix-collect-garbage

查看<直接>安装的包的位置(绝对路径)

使用这个命令, 可以较为方便的查询出某个 Python 包的位置, 并按需加入 path. 这样就不需要使用 nix-shell -p xxx 去找了.

需要注意, 用nix-env -iA 安装的时候, 依赖不会进入nix-env -q的列表.

nix-env -q --out-path

查找 nix store 中安装的包<直接+间接>

nix 安装的所有的包都在这里. 比如要找xeger

ls -alh /nix/store/ | grep xeger

常用 nix-env 命令

参考NixOS Wiki

说明 命令
Searching for packages nix search nixpkgs packagename
Installing a package nix-env -iA packagename
List installed packages nix-env -q
Uninstall packages nix-env -e packagename
Upgrade packages nix-env -u