如何让文件魔术模块在 Alpine Linux 上运行?

Posted

技术标签:

【中文标题】如何让文件魔术模块在 Alpine Linux 上运行?【英文标题】:How to get the file-magic module working on Alpine Linux? 【发布时间】:2019-05-24 23:26:30 【问题描述】:

我正在尝试在 Alpine Linux 上使用 file-magic,但每当我导入 magic 模块时,它就会不断出现 AttributeError: Symbol not found: magic_open

我注意到有两个 Python 模块具有相同的 magic 命名空间,但由于大多数 Linux 发行版似乎使用 file-magic 而不是 python-magic,我决定让我的模块依赖于前者。但是在 Alpine 上,只有 python-magic 似乎有效:

设置 Alpine 并安装 libmagic:

$ docker run --rm -it python:3-alpine /bin/sh
/ # apk add libmagic
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/1) Installing libmagic (5.32-r0)
OK: 21 MiB in 35 packages

安装文件魔法:

/ # pip install file-magic
Collecting file-magic
  Downloading https://files.pythonhosted.org/packages/bb/7e/b256e53a6558afd348387c3119dc4a1e3003d36030584a427168c8d72a7a/file_magic-0.4.0-py3-none-any.whl
Installing collected packages: file-magic
Successfully installed file-magic-0.4.0

但它不起作用:

/ # python
Python 3.7.1 (default, Dec 21 2018, 03:21:42) 
[GCC 6.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import magic
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/magic.py", line 61, in <module>
    _open = _libraries['magic'].magic_open
  File "/usr/local/lib/python3.7/ctypes/__init__.py", line 369, in __getattr__
    func = self.__getitem__(name)
  File "/usr/local/lib/python3.7/ctypes/__init__.py", line 374, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: Symbol not found: magic_open
>>> 

用 python-magic 替换 file-magic:

$ pip uninstall file-magic
Uninstalling file-magic-0.4.0:
  Would remove:
    /usr/local/lib/python3.7/site-packages/file_magic-0.4.0.dist-info/*
    /usr/local/lib/python3.7/site-packages/magic.py
Proceed (y/n)? y
  Successfully uninstalled file-magic-0.4.0

/ # pip install python-magic
Collecting python-magic
  Downloading https://files.pythonhosted.org/packages/42/a1/76d30c79992e3750dac6790ce16f056f870d368ba142f83f75f694d93001/python_magic-0.4.15-py2.py3-none-any.whl
Installing collected packages: python-magic
Successfully installed python-magic-0.4.15

有效:

/ # python
Python 3.7.1 (default, Dec 21 2018, 03:21:42) 
[GCC 6.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import magic
>>> 

我知道每个发行版都有它的怪癖,我想适应,但我现在不知道该怎么做。有没有办法定义模块的 setup.py 来解决这种情况?有没有办法调整 Docker 容器以使用文件魔术?在这种情况下,正确的做法是什么?

【问题讨论】:

【参考方案1】:

Python-Magic 为 Alpine Linux 提供了 a hard-coded fallback,因此您可能很难使用 file-magic,它只使用 ctypes.util.find_library('magic') 并且显然找不到您的库。

ctypes.util.find_library 的确切行为是pretty complicated,但如果您跟踪代码并查看它尝试在您的平台上使用哪些方法,您可能会找到一种方法来找到库(可能是@ 987654327@、/sbin/ldconfigobjdump)。

另一个解决方案是修补 ctypes.py 以正确处理像 Alpine 这样的系统:

wget https://patch-diff.githubusercontent.com/raw/python/cpython/pull/10461.patch -O - | patch /usr/local/lib/python3.7/ctypes/util.py

现在你只需要设置LD_LIBRARY_PATH,Python就可以找到这个库了:

/ # LD_LIBRARY_PATH="/usr/lib/" python -c "import ctypes.util; print(ctypes.util.find_library('magic'))"
libmagic.so.1

【讨论】:

哇。一定有比这更简单的方法,不是吗?其他需要 libmagic 的软件包如何跨发行版进行移植? @DanielQuinn:Alpine 设法没有允许ctypesfind_library 工作的包组合。 It's a known bug 所以您可以等待几个月(或在这种情况下为几年)在上游修复它或自己应用补丁。 哇。很高兴知道!我想我会将上面的内容添加到我的 Dockerfile 中,并在我的模块的文档中包含对此的引用。

以上是关于如何让文件魔术模块在 Alpine Linux 上运行?的主要内容,如果未能解决你的问题,请参考以下文章

在 alpine linux 上执行 mongodb 二进制文件

“找不到 jpeg 的头文件或库文件”在 Alpine Linux 上安装 Pillow

在 Alpine Linux 上安装 Pillow 时没有这样的文件或目录“limits.h”

如何在 Linux 中使用 Alpine 在命令行里访问 Gmail

如何创建基于Alpine Linux的JRE环境

如何让 /etc/profile 在 Alpine / Docker 中自动运行