Python新手:GLPK构建不正确/导入错误

1 投票
2 回答
2015 浏览
提问于 2025-04-15 22:07

这是一个初学者的问题,跟这个问题有关,之前有人推荐我使用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

我猜可能是某些东西没有正确链接到其他地方,可能与路径和环境变量有关。不过,这里是我在命令行操作时遇到的困难,我不知道接下来该怎么做。

编辑

  1. 我可以从命令行运行GLPK求解器(glpsol),所以我知道它至少在理论上是有效的。

  2. 之前我尝试使用MacPorts安装一个版本的GLPK,但后来我已经卸载了这个版本,尽管是通过MacPorts卸载的。

  3. 这是使用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 个回答

1

这个问题其实并不是特定于Python的。glpk模块是一个扩展模块,它是一个C语言的共享库,Python会加载这个库。这个C语言的共享库依赖于它所封装的GLPK C库;加载扩展模块时应该会同时加载GLPK C库,这样扩展模块才能使用GLPK C库中的一些功能,比如__glp_lpx_print_ips。看起来在这个过程中出现了问题,可能有几个原因:

  1. 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共享库的(还有其他共享库)。

  2. glpk.so扩展模块可能正确链接了GLPK C库,但动态链接器可能找不到这个C库。通常这会产生不同的警告(关于找不到C库),但在MacOS上可能不会出现这种情况。你可以再次使用ldd工具来查看:它会列出依赖关系,但不会显示实际加载的文件(会显示“未找到”)。

    这通常是因为没有安装C库,或者安装在了动态链接器不知道去查找的地方。不幸的是,我不太清楚MacOS X是如何查找库的,以及如何修改它扫描的路径。(在大多数UNIX系统上,你需要编辑/etc/ld.so.conf/etc/ld.so.conf.d/中的某个文件,或者运行ldconfig -m。)

  3. glpk.so扩展模块可能链接正确,动态链接器也能正确找到这个模块,但GLPK扩展模块可能根本没有定义这个符号。这可能是GLPK的一个bug,或者是因为动态链接器找到了一个不同的GLPK C库(版本不同,或者构建方式不同),也可能是因为GLPK C库的编译方式和glpk.so扩展模块不同。这种情况比较难以诊断,因为需要深入查看实际的C库符号和编译时使用的头文件。

综合考虑,我猜问题最可能是第二种情况。这是最常见的问题,尤其是在安装到/usr/local时,这通常是运行./configure而不加--prefix参数时的默认行为。

1

问题解决了!

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位二进制文件下运行得更好。

撰写回答