导入sqlite3模块时出现Python ImportError
我正在为一个基于ARM的嵌入式设备交叉编译Python 2.7.3。我已经成功编译了它(根据这些说明:http://randomsplat.com/id5-cross-compiling-python-for-embedded-linux.html),并且在目标设备上所有测试都通过了,所以我对这个编译过程很有信心。我还交叉编译了sqlite3(版本3.8.5),并把它包含在Python的交叉编译过程中,似乎也没问题(在编译结束时,它不再出现在未找到的模块列表中)。
不过,我在目标设备上导入sqlite3库时遇到了困难,出现了下面的错误(Python是用-v标志运行的)。
Python 2.7.3 (default, Jul 7 2014, 19:06:12)
[GCC 3.4.6] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
import sqlite3 # directory /mnt/card/arm-python/lib/python2.7/sqlite3
# /mnt/card/arm-python/lib/python2.7/sqlite3/__init__.pyc matches /mnt/card/arm-python/lib/python2.7/sqlite3/__init__.py
import sqlite3 # precompiled from /mnt/card/arm-python/lib/python2.7/sqlite3/__init__.pyc
# /mnt/card/arm-python/lib/python2.7/sqlite3/dbapi2.pyc matches /mnt/card/arm-python/lib/python2.7/sqlite3/dbapi2.py
import sqlite3.dbapi2 # precompiled from /mnt/card/arm-python/lib/python2.7/sqlite3/dbapi2.pyc
dlopen("/mnt/card/arm-python/lib/python2.7/lib-dynload/datetime.so", 2);
import datetime # dynamically loaded from /mnt/card/arm-python/lib/python2.7/lib-dynload/datetime.so
dlopen("/mnt/card/arm-python/lib/python2.7/lib-dynload/time.so", 2);
import time # dynamically loaded from /mnt/card/arm-python/lib/python2.7/lib-dynload/time.so
dlopen("/mnt/card/arm-python/lib/python2.7/lib-dynload/_sqlite3.so", 2);
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/mnt/card/arm-python/lib/python2.7/sqlite3/__init__.py", line 24, in <module>
from dbapi2 import *
File "/mnt/card/arm-python/lib/python2.7/sqlite3/dbapi2.py", line 27, in <module>
from _sqlite3 import *
ImportError: File not found
看起来它在抱怨“文件未找到”,但我检查了输出中列出的所有路径,所有文件似乎都存在。我可以做些什么来进一步诊断这个问题呢?
1 个回答
我虽然搞定了这个问题,但其实对发生了什么并不是特别明白,因为我对编译C/C++代码和静态/动态库的链接过程不太熟悉。也许有人能帮我解释一下这里到底发生了什么。无论如何,我是这样解决的。
首先,我在Python进程上运行了strace(一个Linux调试工具):
strace /mnt/card/arm-python/bin/python
这会在Python进程启动时输出很多信息,等它稳定下来后,我尝试导入sqlite库:
import sqlite3
这时又会输出更多信息,大部分是关于打开你要导入的模块相关文件的。我注意到它成功打开了_sqlite3.so
,但不久之后它尝试加载libsqlite3.so
,结果在库路径($LD_LIBRARY_PATH)中找不到这个文件。
open("/mnt/card/arm-python/lib/python2.7/lib-dynload/_sqlite3.so", O_RDONLY|O_LARGEFILE) = 5
...
open("/lib/libsqlite3.so.0", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libsqlite3.so.0", O_RDONLY) = -1 ENOENT (No such file or directory)
于是,我把在我的构建机器上的交叉编译sqlite库中的libsqlite3.so.0.8.6
从/lib目录复制到嵌入式ARM设备的/mnt/card
,并把它重命名为libsqlite3.so.0
。接着,我把/mnt/card
添加到$LD_LIBRARY_PATH中,因为这个路径下的现有位置都在只读文件系统上。
然后我再次尝试导入sqlite3,结果一切都正常工作了。那么,lib-dynload
里的东西和libsqlite3.so.0
的作用是什么呢?