Python新手:GLPK构建不正确/导入错误
这是一个初学者的问题,跟这个问题有关,之前有人推荐我使用GLPK。
我正在尝试让PyGLPK运行起来,它是一个用于GNU线性规划工具包的Python绑定。但是无论我怎么做,似乎都无法正确构建和安装GLPK,以便Python能够找到它。我已经按照说明运行了./configure、make和sudo make install来安装GLPK库,并且也跟着PyGLPK的说明进行了操作。
具体来说,我遇到的错误是:
>>> import glpk
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site- packages/glpk.so, 2): Symbol not found: __glp_lpx_print_ips
Referenced from: /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/glpk.so
Expected in: dynamic lookup
我猜可能是某些东西没有正确链接到其他地方,可能与路径和环境变量有关。不过,这里是我在命令行操作时遇到的困难,我不知道接下来该怎么做。
编辑
我可以从命令行运行GLPK求解器(
glpsol
),所以我知道它至少在理论上是有效的。之前我尝试使用MacPorts安装一个版本的GLPK,但后来我已经卸载了这个版本,尽管是通过MacPorts卸载的。
这是使用
otool -L
的结果,听说这是OS X对ldd
的回应:/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/glpk.so: /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11)
再次强调,这个问题可能有简单的解决办法,但我在Google上用我知道的术语搜索时没有找到任何有用的信息。
2 个回答
这个问题其实并不是特定于Python的。glpk
模块是一个扩展模块,它是一个C语言的共享库,Python会加载这个库。这个C语言的共享库依赖于它所封装的GLPK C库;加载扩展模块时应该会同时加载GLPK C库,这样扩展模块才能使用GLPK C库中的一些功能,比如__glp_lpx_print_ips
。看起来在这个过程中出现了问题,可能有几个原因:
glpk.so
扩展模块可能根本没有链接到GLPK C库。这意味着在构建这个模块时没有使用必要的-l
参数来链接GLPK库,这样问题就出在glpk
扩展模块的构建过程中。你可以使用ldd
工具来检查glpk.so
是否依赖于C库。例如:% ldd /usr/lib/python2.6/lib-dynload/gdbm.so linux-gate.so.1 => (0xb77bb000) libgdbm.so.3 => /usr/lib/libgdbm.so.3 (0xb7799000) libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb7780000) libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7639000) /lib/ld-linux.so.2 (0xb77bc000)
这显示了我的
gdbm
扩展模块是链接到libgdbm
共享库的(还有其他共享库)。glpk.so
扩展模块可能正确链接了GLPK C库,但动态链接器可能找不到这个C库。通常这会产生不同的警告(关于找不到C库),但在MacOS上可能不会出现这种情况。你可以再次使用ldd
工具来查看:它会列出依赖关系,但不会显示实际加载的文件(会显示“未找到”)。这通常是因为没有安装C库,或者安装在了动态链接器不知道去查找的地方。不幸的是,我不太清楚MacOS X是如何查找库的,以及如何修改它扫描的路径。(在大多数UNIX系统上,你需要编辑
/etc/ld.so.conf
或/etc/ld.so.conf.d/
中的某个文件,或者运行ldconfig -m
。)glpk.so
扩展模块可能链接正确,动态链接器也能正确找到这个模块,但GLPK扩展模块可能根本没有定义这个符号。这可能是GLPK的一个bug,或者是因为动态链接器找到了一个不同的GLPK C库(版本不同,或者构建方式不同),也可能是因为GLPK C库的编译方式和glpk.so
扩展模块不同。这种情况比较难以诊断,因为需要深入查看实际的C库符号和编译时使用的头文件。
综合考虑,我猜问题最可能是第二种情况。这是最常见的问题,尤其是在安装到/usr/local
时,这通常是运行./configure
而不加--prefix
参数时的默认行为。
问题解决了!
Thomas Wouter的第一个建议最接近问题的核心:glpk.so
模块根本没有和C库连接起来。原因是make
在构建原始的GLPK库时使用的是gcc4.2
,并指定了64位架构,而Python的distutils
模块却坚持要用gcc-4.0
来构建PyGLPK的源代码,并且是32位架构。
因为我不知道怎么给distutils
添加编译器选项,所以我干脆重新构建了GLPK库,强制使用distutils
的编译器选项。最终,这个方法成功了。
这似乎是OS X 10.6的一个问题。./configure
脚本会查询系统架构,默认情况下,我认为是x86_64
,尽管Python 2.6在32位二进制文件下运行得更好。