在Python模块发行版中查找文件
我写了一个Python包,这个包里有一个bsddb数据库,里面存放了一些预先计算好的值,这些值是为了加速一些比较耗时的计算。为了简单起见,我的安装脚本把数据库文件放在和访问这个数据库的代码同一个目录下(在Unix系统上,类似于/usr/lib/python2.5/site-packages/mypackage/)。
我该如何存储这个数据库文件的最终位置,以便我的代码可以访问它呢?现在,我是用一个小技巧,利用了模块中的__file__
变量来获取数据库的位置:
dbname = os.path.join(os.path.dirname(__file__), "database.dat")
这样做是有效的,但我觉得有点...像是变通的办法。有没有更好的方法呢?我希望安装脚本能直接从distutils模块获取最终的安装位置,然后把这个信息放到一个名为"dbconfig.py"的文件里,这个文件和访问数据库的代码一起安装。
4 个回答
这可能是个不错的方法,不用用到像setuptools这样更复杂的工具来把文件安装到正确的位置。
不过要注意,这种方法有个问题,因为在一些有真正安全框架的操作系统(比如UNIX等)上,运行你脚本的用户可能没有权限去访问安装在系统目录里的数据库。
使用 pkgutil.get_data
。它和 pkg_resources.resource_stream
是亲戚,但属于标准库的一部分,应该可以在普通的文件系统安装、压缩包以及其他导入方式中都能正常工作。
试试使用pkg_resources,它是setuptools的一部分(我现在能接触到的所有Python版本都有这个工具):
>>> import pkg_resources
>>> pkg_resources.resource_filename(__name__, "foo.config")
'foo.config'
>>> pkg_resources.resource_filename('tempfile', "foo.config")
'/usr/lib/python2.4/foo.config'
关于如何使用pkg_resources来获取资源,您可以在egg页面和pkg_resources页面找到更多讨论。
另外要注意,如果可以的话,最好使用pkg_resources.resource_stream或pkg_resources.resource_string,因为如果这个包是一个egg的一部分,resource_filename会把文件复制到一个临时目录。