我一直在构建一个奇点容器来运行一些 python 代码,尽管阅读了奇点文档,但我无法理解错误/行为。
首先,容器是从 docker 引导的 Ubuntu18.04,即:
Bootstrap: docker
From: ubuntu:18.04
我需要使用一个 python 模块(神经元),它需要事先编译等。%post
我在定义文件部分编译代码并添加环境变量:
echo 'export PATH=$PATH:/usr/local/nrn/x86_64/bin' >>$SINGULARITY_ENVIRONMENT
echo 'export LD_LIBRARY_PATH=/usr/local/nrn/x86_64/lib:$LD_LIBRARY_PATH' >>$SINGULARITY_ENVIRONMENT
我可以构建容器而没有太多问题(使用sudo singularity build --sandbox
)。但是我一直在尝试运行一个测试脚本(test.py)以确保一切都按预期工作。在脚本中,我导入有问题的模块(神经元),然后尝试将列表保存到 csv 以确保可以正确保存数据。所以它看起来像这样:
import neuron #this fails and gives an unusual error in specific circumstances I don't understand (described below)
import numpy as np
some_data = [1,2,3]
np.savetxt('test_results.csv',np.asarray(some_data),delimiter=',')
根据我在使用时提供的标志,singularity exec
我会得到不同的结果,我不明白(或知道从哪里开始理解——这是神经元、奇点还是ubuntu
问题?)。
为了完整起见,容器(和 test.py)位于我从中运行这些命令的同一目录中(在我的示例中为 dir)。因此,如果我挂载 $HOME,则不使用该--no-home
标志并尝试像这样运行 test.py:
singularity exec --writable --bind /home/bidby/path/to/some/dir:/mnt my_container.simg python3 /mnt/test.py
我得到一个像这样的错误:dlopen failed - x86_64/.libs/libnrnmech.so: undefined symbol: celsius
我已经尝试过用谷歌搜索,可能是一个 c++ 链接错误(但我只知道 python,所以调试它并不容易)。
但是,如果我使用--no-home
标志,即:
singularity exec --no-home --writable --bind /home/bidby/path/to/some/dir:/mnt my_container.simg python3 /mnt/test.py
然后模块成功导入并出现新错误:
Traceback (most recent call last):
File "/mnt/test.py", line 15, in <module>
np.savetxt('test_results.csv',np.asarray(some_data),delimiter=',')
File "/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py", line 1352, in savetxt
open(fname, 'wt').close()
PermissionError: [Errno 13] Permission denied: 'test_results.csv'
我已经连续几天在谷歌上搜索这个,但我无法弄清楚问题是什么。根据我所学和测试的内容,我认为这可能与环境变量如何传递到容器中有关,尽管我无权在此处保存的原因超出了我的范围。但我觉得如果我能理解为什么使用--no-home
标志会影响模块导入,这可能会得到解决。
这可能无助于解决问题,但我注意到/尝试过的其他事情:
如果我使用该--containall
标志,我可以毫无问题地运行 test.py,但是我尝试保存的 csv 文件永远找不到。我检查了文档说:
使用 --containall(或简称 -C)标志,$HOME 不会被挂载,并且会在 $HOME 点创建一个虚拟绑定挂载。您不能使用 -B`(或 --bind)来绑定您的 $HOME 目录,因为它会创建一个空挂载。因此,如果您的文件位于 /home/user 的映像中, --containall 标志会将它们全部隐藏。
我认为这个“虚拟绑定安装”是文件被写入的位置,因此我永远无法真正找到它。
如果我壳到容器中,带有sudo
和--writable
标志,我可以毫无问题地导入神经元。如果我不使用这些标志中的任何一个,那么我会从上面得到相同的“未定义符号”错误。
如果我不导出 LD_LIBRARY_PATH,那么我会得到一个不同的 dlopen 错误,它指的是不同的 .so 文件,说该文件不存在 - 这再次证实了我的想法,即这是一个路径问题。
我知道我没有包含足够的代码来重现这个错误,因为我猜没有人有时间/精力来构建这个容器(因为它相当大),但我认为我已经包含了最相关的部分。如果需要,我们很乐意添加更多内容。
调试这对我来说是一场噩梦,如果有人能指出我应该在谷歌上搜索的正确方向,我将不胜感激。