ここではNixOSとPythonとmatplotlibでグラフを出力するための方法を記載する。
グラフを表示するケースとして以下の2つのケースを考える。
- (パターン1)NixだけでPythonのパッケージ管理をする方法
- (パターン2)astral-sh/uvでPythonのパッケージ管理をする方法
前者はあっさり終わるが、後者はすんなり動かないので工夫が必要。具体的には以下の工夫がいる。
- 共有ライブラリのパスが解決できずエラーになる: uvが外部から持ってきたライブラリにプリコンパイルされたCの共有ライブラリファイルがあるため。
LD_LIBRARY_PATH
の指定をする必要がある - tkinterのモジュールが解決できず、グラフが出力されない:nixpkgsに入っているPythonのデフォルトにはtkinterがついてないため。overlayとoverrideを使い、tkinter入りのPythonを用意する
NixOSでほかのLinuxディストリビューションと同じようなことをしようとするとひと手間必要という良い例かも。
なお、今回紹介するのはあくまで NixOS 上での例である。例えばNixOSでないほかのOSでNixパッケージマネージャだけ導入しているようなケースでは、(環境によるが)パターン2は特に工夫なく動くかもしれない。
また、今回使うuvは0.4.8である。uvは開発が早いので、数か月後にはこの記事通りに動かなくなってるかも。
1
2
| [bombrary@nixos:~/example]$ uv --version
uv 0.4.8
|
(パターン1)Nixを用いたパッケージ管理例#
はじめに、flake.nix
ファイルを作る。
1
2
| [bombrary@nixos:~/example]$ nix flake init
wrote: /home/bombrary/example/flake.nix
|
以下のような flake.nix
を書く。python.withPackagesを使うことで、特定のパッケージが入ったPythonを作ることができる(イメージ的には、venvと同じものを /nix/store/
で管理する感じ)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| {
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
my-python = pkgs.python312.withPackages (python-pkgs: [
python-pkgs.matplotlib
]);
in
{
devShells.x86_64-linux.default = pkgs.mkShell {
packages = with pkgs; [
my-python
];
};
};
}
|
nix develop
して、上記で定義したPython環境が使える状態にする。
1
| [bombrary@nixos:~/example]$ nix develop
|
Pythonが入っているディレクトリの周辺を探ってみると、同パッケージディレクトリの /lib/python3.12/site-packages
ディレクトリにmatplotlibが確かにあることがわかる。
1
2
3
4
5
6
7
8
9
| [bombrary@nixos:~]$ which python
/nix/store/fm0p1f5fl4pvb06y07zpivsqx4rlyq2z-python3-3.12.5-env/bin/python
[bombrary@nixos:~]$ ls /nix/store/fm0p1f5fl4pvb06y07zpivsqx4rlyq2z-python3-3.12.5-env/lib/python3.12/site-packages/
contourpy defusedxml kiwisolver-1.4.5.dist-info numpy-1.26.4.dist-info PIL pyparsing-3.1.2.dist-info six.py
contourpy-1.2.1.dist-info defusedxml-0.8.0rc2.dist-info matplotlib olefile pillow-10.4.0.dist-info python_dateutil-2.9.0.post0.dist-info _sysconfigdata__linux_x86_64-linux-gnu.py
cycler fontTools matplotlib-3.9.1.dist-info olefile-0.47.dist-info __pycache__ README.txt _tkinter.cpython-312-x86_64-linux-gnu.so
cycler-0.12.1.dist-info fonttools-4.53.1.dist-info mpl_toolkits packaging pylab.py sitecustomize.py
dateutil kiwisolver numpy packaging-24.1.dist-info pyparsing six-1.16.0.dist-info
|
試しにグラフを出力してみよう。以下のコードを main.py
として保存する。
1
2
3
4
5
6
| import matplotlib
from matplotlib import pyplot as plt
fig, ax = plt.subplots()
ax.plot([1,2,3], [1,2,3])
plt.show()
|
以下で main.py
を実行すると、グラフが出力される。
1
| [bombrary@nixos:~/example]$ python main.py
|
(パターン2)uvを用いたパッケージ管理例#
NixでPythonのパッケージの管理はせず、別のツールで管理したい人もいるかもしれない。ここではuvを用いる状況を想定する。
この場合、以下の課題が存在する。
- 共有ライブラリが見つからない問題:NumPyなどはCでプリコンパイルされたバイナリを持ってるので、それが外部の共有ライブラリを要求し見つからずエラーになる
- tkinterが見つからない問題:nixpkgsで提供されているデフォルトのPythonにはtkinterが付属していないので、付属済みのPythonを用意する必要がある
次の作業のために、先ほどの nix develop
からは抜けておく。
共有ライブラリが見つからない問題:LD_LIBRARY_PATHの話#
共有ライブラリが見つからないエラー#
続いて、以下のようにuvだけ導入した状態にする。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| {
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
in
{
devShells.x86_64-linux.default = pkgs.mkShell {
packages = with pkgs; [
uv
];
};
};
}
|
nix develop
で uv が入ったシェルに入り、プロジェクトの初期化とmatplotlibの導入を行う。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| [bombrary@nixos:~/example]$ nix develop
[bombrary@nixos:~/example]$ uv init
Initialized project `example`
[bombrary@nixos:~/example]$ uv add matplotlib
Using Python 3.12.5 interpreter at: /nix/store/h3i0acpmr8mrjx07519xxmidv8mpax4y-python3-3.12.5/bin/python3.12
Creating virtualenv at: .venv
Resolved 12 packages in 244ms
Prepared 11 packages in 669ms
Installed 11 packages in 21ms
+ contourpy==1.3.0
+ cycler==0.12.1
+ fonttools==4.53.1
+ kiwisolver==1.4.7
+ matplotlib==3.9.2
+ numpy==2.1.1
+ packaging==24.1
+ pillow==10.4.0
+ pyparsing==3.1.4
+ python-dateutil==2.9.0.post0
+ six==1.16.0
|
ところが、uv経由で main.py
を実行しようとすると、次のエラーが出力される。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| [bombrary@nixos:~/example]$ uv run python main.py
Traceback (most recent call last):
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/_core/__init__.py", line 23, in <module>
from . import multiarray
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/_core/multiarray.py", line 10, in <module>
from . import overrides
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/_core/overrides.py", line 8, in <module>
from numpy._core._multiarray_umath import (
ImportError: libstdc++.so.6: cannot open shared object file: No such file or directory
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/__init__.py", line 114, in <module>
from numpy.__config__ import show as show_config
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/__config__.py", line 4, in <module>
from numpy._core._multiarray_umath import (
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/_core/__init__.py", line 49, in <module>
raise ImportError(msg)
ImportError:
IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
Importing the numpy C-extensions failed. This error can happen for
many reasons, often due to issues with your setup or how NumPy was
installed.
We have compiled some common reasons and troubleshooting tips at:
https://numpy.org/devdocs/user/troubleshooting-importerror.html
Please note and check the following:
* The Python version is: Python3.12 from "/home/bombrary/example/.venv/bin/python3"
* The NumPy version is: "2.1.1"
and make sure that they are the versions you expect.
Please carefully study the documentation linked above for further help.
Original error was: libstdc++.so.6: cannot open shared object file: No such file or directory
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/bombrary/example/main.py", line 1, in <module>
import matplotlib
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/matplotlib/__init__.py", line 159, in <module>
from . import _api, _version, cbook, _docstring, rcsetup
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/matplotlib/cbook.py", line 24, in <module>
import numpy as np
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/numpy/__init__.py", line 119, in <module>
raise ImportError(msg) from e
ImportError: Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python interpreter from there.
|
エラーの内容を見てみると、どうやらNumPyが裏で読まれ、その際に libstdc++.so.6
が無くてエラーが出ているらしい。
NumPyは一部がCで書かれているため (参考)、いくつかの構成ファイルはPythonコードではなく、Cでコンパイルされた共有ライブラリである。これらがlibstdc++.so.6
を要求しているが、そのパスが解決できずエラーになっている。普通このファイルは /lib/
配下にはるはずだが、NixOSはビルドの再現性の担保のために /lib/
を捨てているのでこのような状況になっている。
1
2
3
4
5
6
7
8
9
10
11
12
| [bombrary@nixos:~/example]$ ldd ./.venv/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so
linux-vdso.so.1 (0x00007fff3fffe000)
libscipy_openblas64_-ff651d7f.so => /home/bombrary/example/./.venv/lib/python3.12/site-packages/numpy/_core/../../numpy.libs/libscipy_openblas64_-ff651d7f.so (0x00007f5d6da00000)
libstdc++.so.6 => not found
libm.so.6 => /nix/store/r8qsxm85rlxzdac7988psm7gimg4dl3q-glibc-2.39-52/lib/libm.so.6 (0x00007f5d6ef1d000)
libgcc_s.so.1 => /nix/store/k8aiaw3mslh4120lah1ssg3r6xa46cz1-xgcc-13.2.0-libgcc/lib/libgcc_s.so.1 (0x00007f5d6eef8000)
libc.so.6 => /nix/store/r8qsxm85rlxzdac7988psm7gimg4dl3q-glibc-2.39-52/lib/libc.so.6 (0x00007f5d6d813000)
/nix/store/r8qsxm85rlxzdac7988psm7gimg4dl3q-glibc-2.39-52/lib64/ld-linux-x86-64.so.2 (0x00007f5d6f9b3000)
libpthread.so.0 => /nix/store/r8qsxm85rlxzdac7988psm7gimg4dl3q-glibc-2.39-52/lib/libpthread.so.0 (0x00007f5d6f9aa000)
libgfortran-040039e1-0352e75f.so.5.0.0 => /home/bombrary/example/./.venv/lib/python3.12/site-packages/numpy/_core/../../numpy.libs/libgfortran-040039e1-0352e75f.so.5.0.0 (0x00007f5d6d200000)
libquadmath-96973f99-934c22de.so.0.0.0 => /home/bombrary/example/./.venv/lib/python3.12/site-packages/numpy/_core/../../numpy.libs/libquadmath-96973f99-934c22de.so.0.0.0 (0x00007f5d6ce00000)
libz.so.1 => not found
|
ちなみに /nix/store/...
をうまく解決できているやつがちょこちょこいるが、どうやって解決しているのかは LD_DEBUG=files,libs
をつけて ldd
を実行すると分かる。
1
2
3
4
5
6
7
| [bombrary@nixos:~/example]$ LD_DEBUG=files,libs ldd ./.venv/lib/python3.12/site-packages/numpy/_core/_multiarray_umath.cpython-312-x86_64-linux-gnu.so
14590:
14590: file=libreadline.so.8 [0]; needed by /bin/sh [0]
14590: find library=libreadline.so.8 [0]; searching
14590: search path=/nix/store/zkmxm571ds0j8gzchb2dxs1hizmr10ad-ncurses-6.4/lib/glibc-hwcaps/x86-64-v3:/nix/store/zkmxm571ds0j8gzchb2dxs1hizmr10ad-ncurses-6.4/lib/glibc-hwcaps/x86-64-v2:/nix/store/zkmxm571ds0j8gzchb2dxs1hizmr10ad-ncurses-6.4/lib:/nix/store/x3axw06zyyw0dsabfgichjilqqs0i9vc-readline-8.2p10/lib/glibc-hwcaps/x86-64-v3:/nix/store/x3axw06zyyw0dsabfgichjilqqs0i9vc-readline-8.2p10/lib/glibc-hwcaps/x86-64-v2:/nix/store/x3axw06zyyw0dsabfgichjilqqs0i9vc-readline-8.2p10/lib (RUNPATH from file /bin/sh)
14590: trying file=/nix/store/zkmxm571ds0j8gzchb2dxs1hizmr10ad-ncurses-6.4/lib/glibc-hwcaps/x86-64-v3/libreadline.so.8
...
|
ログ (RUNPATH from file /bin/sh)
を見るに、どうやら /bin/sh
のRUNPATHから取り出しているようだ。
LD_LIBRARY_PATHの設定#
libstdc++.so.6
のパスをどうにかして解決しなければいけない。 patchelf --set-rpath
をやろうにも共有ライブラリの量が多すぎるので、ここではLD_LIBRARY_PATH
に設定する解決策を紹介する。 まず libstcd++.so.6
の場所を把握する。探すと libgcc パッケージにあることがわかる。
1
2
| [bombrary@nixos:~/example]$ ls $(nix eval --raw 'nixpkgs#libgcc.lib')/lib/libstdc++.so.6
/nix/store/22nxhmsfcv2q2rpkmfvzwg2w5z1l231z-gcc-13.3.0-lib/lib/libstdc++.so.6
|
そこで、flake.nix
を以下のようにして、 nix develop
をやり直す。
pkgs.mkShell
の引数に指定した attribute は、環境変数として nix develop
後に設定される。そのため LD_LIBRARY_PATH = ...
を設定すればこれが環境変数になる- lib.string.makeLibraryPath またはこれと同義の
lib.makeLibraryPath
で、パッケージの /lib
へのパスをコロン :
でつなげた文字列を生成する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| {
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
in
{
devShells.x86_64-linux.default = pkgs.mkShell {
packages = with pkgs; [
uv
];
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; [
libgcc.lib
]);
};
};
}
|
すると、 LD_LIBRARY_PATH
にパスが設定されていることがわかる。
1
2
| [bombrary@nixos:~/example]$ echo $LD_LIBRARY_PATH
/nix/store/22nxhmsfcv2q2rpkmfvzwg2w5z1l231z-gcc-13.3.0-lib/lib
|
これで、共有ライブラリが解決できないというエラーはでなくなる。
tkinterが見つからない問題:overlayの話#
tkinterが見つからないエラー#
共有ライブラリが解決できないエラーは無くなったが、代わりにWarningが出ており、matplotlibのウインドウは出現しない。
1
2
3
| [bombrary@nixos:~/example]$ uv run python main.py
/home/bombrary/example/main.py:6: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
plt.show()
|
tkinterが入っていればそれを用いてUIが作成されウインドウが出現されるはずである。試しに無理やりTkを使って出力させるよう、Pythonのコードに以下の一文を加える。
1
2
| import matplotlib
matplotlib.use("TkAgg")
|
すると、以下のエラーが出る。どうやらtkinterが入ってないらしい。
1
2
3
4
5
6
7
8
| File "/home/bombrary/example/.venv/lib/python3.12/site-packages/matplotlib/backends/backend_tkagg.py", line 1, in <module>
from . import _backend_tk
File "/home/bombrary/example/.venv/lib/python3.12/site-packages/matplotlib/backends/_backend_tk.py", line 9, in <module>
import tkinter as tk
File "/nix/store/h3i0acpmr8mrjx07519xxmidv8mpax4y-python3-3.12.5/lib/python3.12/tkinter/__init__.py", line 38, in <module>
import _tkinter # If this fails your Python may not be configured for Tk
^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named '_tkinter'
|
そもそもuvから動くPythonはいったい何者なのだろうか? これは uv python list
コマンドで確認できる。どうやら /nix/store/
にあるPythonを参照しているようだ。つまりnixpkgs上で管理されているPythonである。
1
2
3
4
5
6
7
| [bombrary@nixos:~/example]$ uv python list
cpython-3.12.5-linux-x86_64-gnu /nix/store/h3i0acpmr8mrjx07519xxmidv8mpax4y-python3-3.12.5/bin/python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/h3i0acpmr8mrjx07519xxmidv8mpax4y-python3-3.12.5/bin/python3 -> python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/h3i0acpmr8mrjx07519xxmidv8mpax4y-python3-3.12.5/bin/python -> python3.12
cpython-3.12.5-linux-x86_64-gnu <download available>
cpython-3.11.9-linux-x86_64-gnu <download available>
...
|
uvでは、Pythonを PATH
環境変数から探す。そしてuvのderivationではpython3Packages.buildPythonApplication
が使われているため、nix develop
実行時にそのパスが PATH
環境変数に指定され、標準でPythonのバイナリが認識できるような状態になっている。
そして、そのPythonについて nixpkgsのドキュメント に書かれているが、tkinterは標準で入っていない。そのため、tkinter入りのPythonを自分で作ってuvが参照するPythonを書き換える必要がある。
overlayとoverrideを用いたパッケージの追加・書き換え#
そこで、tkinterがサポートされたPythonを追加し、それをuvに設定しよう。以下のようにする。nixpkgsの overlay の仕組みを使えば、nixpkgsにパッケージを追加したり、パラメータを変更したりすることができる。具体的には以下を行う。
- nixpkgsに新しい
my-python
というパッケージを追加し、x11のサポートを有効にする - nixpkgsにある
uv
パッケージのパラメータ python3Packages
を、 my-python
のパッケージに変更する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| {
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux.extend
(final: prev: {
my-python312 = prev.python312.override { self = final.my-python; x11Support = true; };
uv = (prev.uv.override { python3Packages = final.my-python.pkgs; });
});
in
{
devShells.x86_64-linux.default = pkgs.mkShell {
packages = with pkgs; [
uv
];
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; [
libgcc.lib
]);
};
};
}
|
これで uv は、x11がサポートされたPythonである my-python
を認識するようになる。ハッシュ値が変わったのがわかるだろう。
1
2
3
4
5
| [bombrary@nixos:~/example]$ uv python list
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python3 -> python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python -> python3.12
cpython-3.12.5-linux-x86_64-gnu <download available>
|
既存の .venv
を消して main.py
を再実行すると、グラフが出力される。
1
2
3
4
5
6
| [bombrary@nixos:~/example]$ rm -rf .venv
[bombrary@nixos:~/example]$ uv run python main.py
Using Python 3.12.5 interpreter at: /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python3.12
Creating virtualenv at: .venv
Installed 11 packages in 26ms
|
この方法の欠点は、nix develop
の初回はuvの再ビルドが行われてしまう点。ビルドには、少なくとも自分の環境だと5分程度かかった。
なお、別バージョンのPythonも使えるようにしたい場合は、次のようにする。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| {
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux.extend
(final: prev: {
my-python312 = prev.python312.override { self = final.my-python312; x11Support = true; };
my-python311 = prev.python311.override { self = final.my-python311; x11Support = true; };
uv = (prev.uv.override { python3Packages = final.my-python312.pkgs; });
});
in
{
devShells.x86_64-linux.default = pkgs.mkShell {
packages = with pkgs; [
uv
my-python311
];
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; [
libgcc.lib
]);
};
};
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| [bombrary@nixos:~/example]$ uv python list
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python3 -> python3.12
cpython-3.12.5-linux-x86_64-gnu /nix/store/lmh3qxw8gr8kr2nz3094id5kk446mdhf-python3-3.12.5/bin/python -> python3.12
cpython-3.12.5-linux-x86_64-gnu <download available>
cpython-3.11.9-linux-x86_64-gnu /nix/store/ycjcblkvvbrhsm2rvmj4d6ddp7a13mh1-python3-3.11.9/bin/python3.11
cpython-3.11.9-linux-x86_64-gnu /nix/store/ycjcblkvvbrhsm2rvmj4d6ddp7a13mh1-python3-3.11.9/bin/python3 -> python3.11
cpython-3.11.9-linux-x86_64-gnu /nix/store/ycjcblkvvbrhsm2rvmj4d6ddp7a13mh1-python3-3.11.9/bin/python -> python3.11
cpython-3.11.9-linux-x86_64-gnu <download available>
cpython-3.10.14-linux-x86_64-gnu <download available>
cpython-3.9.19-linux-x86_64-gnu <download available>
cpython-3.8.19-linux-x86_64-gnu <download available>
cpython-3.7.9-linux-x86_64-gnu <download available>
pypy-3.10.14-linux-x86_64-gnu <download available>
pypy-3.9.19-linux-x86_64-gnu <download available>
pypy-3.8.16-linux-x86_64-gnu <download available>
pypy-3.7.13-linux-x86_64-gnu <download available>
|
なお、今回はx11をサポートするオプションだけを追加した my-python311
と my-python312
を自前で用意したが、代わりにほかのオプションが全部有効になっているバージョンの python311Full
、 python312Full
を使ってもよい(サイズは大きいだろうが、何か開発するうえで必要なパッケージが足りないなどの余計なトラブルが少なく開発できるかも)。
まとめ#
NixOS上でmatplotlibを使いグラフを出力する方法として、Nix単体で完結する方法と、uvを使った方法の2つを紹介した。前者はあっさりできるが、後者は共有ライブラリの設定やPythonの用意が必要であった。
そもそもNixは /nix/store/
上であらゆるコンテンツを管理するよう作られているので、nixファイルを使わずパッケージを管理することはNixの思想から外れているのだろう。なのでそれを無理に動かそうとすると工夫が必要なのは仕方ないのかも、と思った。とはいえケースによっては使いたいときもあるだろうから、その方法を模索することは無駄ではないと思う。
しかし、(もちろんユーザの習熟度にもよるが)普段ユーザがあまり気にしないであろう共有ライブラリの話やNixのoverlayの話が出てくるのはなかなか厄介だなと感じた。自分はただPythonでグラフが描きたいだけなのに、なぜ共有ライブラリとかNixについてを学ばなくてはいけないのだ、みたいな人は少なからずいるのかも…。いや、NixOSを使う人でそんなライトなユーザはあまりいないのだろうか…?
(おまけ:リモートからやる場合)NixOSのXForwardingの設定#
NixOSのデスクトップ環境を直接操作したり、WSL上のNixOSで作業したりする場合は不要だが、リモート上にNixOSがありそこにSSHしてグラフを出力したい場合は、X11 の設定をする必要がある。
X11 の設定をするため、当然だがSSH接続元でXServerが動いている必要がある。最近のWSLなら 標準でX11のサーバーが動いているっぽい。
configuration.nix
に以下を追記する。 services.openssh.settings.X11Forwarding = true
を追記している。
1
2
3
4
5
6
| services.openssh = {
enable = true;
settings = {
X11Forwarding = true;
};
};
|
これでNixOSを再ビルドすると、 /etc/ssh/sshd_config
に X11Forwarding yes
が追加されていることがわかる。
1
2
3
4
| [bombrary@nixos:~]$ sudo nixos-rebuild switch
[bombrary@nixos:~]$ cat /etc/ssh/sshd_config | grep X11Forwarding
X11Forwarding yes
|
いったん再ログインして、xeyesコマンドを実行し、ウインドウが接続元で出力されれば成功。
1
2
3
4
5
6
| at 19:40:22 ❯ ssh -Y bombrary@192.168.11.11
(bombrary@192.168.11.11) Password:
Warning: No xauth data; using fake authentication data for X11 forwarding.
Last login: Sun Sep 15 19:10:40 2024 from 192.168.11.6
[bombrary@nixos:~]$ nix run 'nixpkgs#xorg.xeyes'
|