Python 代码在使用安装工具打包并使用 pip 安装后看不到数据文件



我用setuptools打包了一些python代码。代码使用数据文件,但是使用pip安装包后,代码找不到数据文件。我做错了什么?


以下是文件结构和文件内容。这些文件可以在这里找到。python代码setup.py正在尝试使用mesa/a.txt数据文件。如果我不打包+点化它,代码工作正常。

|
|- tm/
|  |- __init__.py
|  |- test2.py
|- mesa/
|  |- __init__.py
|  |- a.txt
|- MANIFEST.in
|- setup.py

MANIFEST.in

include mesa/a.txt

setup.py

from setuptools import setup
setup(name='bobab',
version='0.1',
py_modules=['tm.test2'],
author_email='x@gmail.com',
package_data = {
'tm': ['mesa/a.txt']
},
)

'mesa/a.txt

hello world!

tm/test2.py

import os
def main():
print 'hi' 
print open(os.path.join('..', 'mesa', 'a.txt'), 'r').read() # print file content
if __name__ == "__main__":
main()

我使用命令python setup.py sdist来创建包。我使用以下命令安装软件包:

unzip bobab-0.1.zip
cd bobab-0.1
python setup.py install

包看不到数据文件mesa/a.txt,如下面的错误消息所示:

Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
>>> import tm.test2
>>> tm.test2.main()
hi
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tm/test2.py", line 5, in main
print open(os.path.join('..', 'mesa', 'a.txt'), 'r').read()
IOError: [Errno 2] No such file or directory: '../mesa/a.txt'

我使用Python 2.7。


下面是打包和安装日志。有趣的是,打包日志提到数据文件mesa/a.txt已添加到包中,但安装日志没有提到它的存在。

包装日志:

C:UsersFranckDocumentsGitHubmiscsrctest>python setu
p.py sdist
running sdist
running egg_info
creating bobab.egg-info
writing bobab.egg-infoPKG-INFO
writing top-level names to bobab.egg-infotop_level.txt
writing dependency_links to bobab.egg-infodependency_links.txt
writing pbr to bobab.egg-infopbr.json
writing manifest file 'bobab.egg-infoSOURCES.txt'
reading manifest file 'bobab.egg-infoSOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'bobab.egg-infoSOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst,
README.txt
running check
warning: check: missing required meta-data: url
warning: check: missing meta-data: either (author and author_email) or (maintain
er and maintainer_email) must be supplied
creating bobab-0.1
creating bobab-0.1bobab.egg-info
creating bobab-0.1mesa
creating bobab-0.1tm
copying files to bobab-0.1...
copying MANIFEST.in -> bobab-0.1
copying setup.py -> bobab-0.1
copying bobab.egg-infoPKG-INFO -> bobab-0.1bobab.egg-info
copying bobab.egg-infoSOURCES.txt -> bobab-0.1bobab.egg-info
copying bobab.egg-infodependency_links.txt -> bobab-0.1bobab.egg-info
copying bobab.egg-infopbr.json -> bobab-0.1bobab.egg-info
copying bobab.egg-infotop_level.txt -> bobab-0.1bobab.egg-info
copying mesaa.txt -> bobab-0.1mesa
copying tm__init__.py -> bobab-0.1tm
copying tmtest2.py -> bobab-0.1tm
Writing bobab-0.1setup.cfg
creating 'distbobab-0.1.zip' and adding 'bobab-0.1' to it
adding 'bobab-0.1MANIFEST.in'
adding 'bobab-0.1PKG-INFO'
adding 'bobab-0.1setup.cfg'
adding 'bobab-0.1setup.py'
adding 'bobab-0.1bobab.egg-infodependency_links.txt'
adding 'bobab-0.1bobab.egg-infopbr.json'
adding 'bobab-0.1bobab.egg-infoPKG-INFO'
adding 'bobab-0.1bobab.egg-infoSOURCES.txt'
adding 'bobab-0.1bobab.egg-infotop_level.txt'
adding 'bobab-0.1mesaa.txt'
adding 'bobab-0.1tmtest2.py'
adding 'bobab-0.1tm__init__.py'
removing 'bobab-0.1' (and everything under it)

安装日志:

(sedona) dernonco@ilcompn0:/mnt/ilcompn0d1/user/dernonco/temp/bobab-0.1$ python setup.py install
running install
running bdist_egg
running egg_info
writing bobab.egg-info/PKG-INFO
writing top-level names to bobab.egg-info/top_level.txt
writing dependency_links to bobab.egg-info/dependency_links.txt
reading manifest file 'bobab.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'bobab.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_py
creating build
creating build/lib.linux-x86_64-2.7
creating build/lib.linux-x86_64-2.7/tm
copying tm/__init__.py -> build/lib.linux-x86_64-2.7/tm
copying tm/test2.py -> build/lib.linux-x86_64-2.7/tm
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/egg
creating build/bdist.linux-x86_64/egg/tm
copying build/lib.linux-x86_64-2.7/tm/__init__.py -> build/bdist.linux-x86_64/egg/tm
copying build/lib.linux-x86_64-2.7/tm/test2.py -> build/bdist.linux-x86_64/egg/tm
byte-compiling build/bdist.linux-x86_64/egg/tm/__init__.py to __init__.pyc
byte-compiling build/bdist.linux-x86_64/egg/tm/test2.py to test2.pyc
creating build/bdist.linux-x86_64/egg/EGG-INFO
copying bobab.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
copying bobab.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying bobab.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying bobab.egg-info/pbr.json -> build/bdist.linux-x86_64/egg/EGG-INFO
copying bobab.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist/bobab-0.1-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing bobab-0.1-py2.7.egg
Copying bobab-0.1-py2.7.egg to /mnt/ilcompn0d1/user/dernonco/pyenv/sedona/lib/python2.7/site-packages
Adding bobab 0.1 to easy-install.pth file
Installed /mnt/ilcompn0d1/user/dernonco/pyenv/sedona/lib/python2.7/site-packages/bobab-0.1-py2.7.egg
Processing dependencies for bobab==0.1
Finished processing dependencies for bobab==0.1

应该调整几件事:

  1. MANIFEST.in仅在打包源 dist 时使用,因此即使使用当前设置python setup.py sdist也会包含mesa/a.txt。二进制分布不是这种情况,bdist_eggbdist_wheel都不会读取MANIFEST.in
  2. package_data通常用于放置在包内的非 python 文件,但mesa不会放置在tmdir 内,因此相对路径是错误的。您可以通过设置虚线路径来规避此问题:

    package_data={'tm': ['../mesa/a.txt']}
    

    但是,如果mesatm包的一部分,则将其放在应有的位置是有意义的。

  3. os.path.join('..', 'mesa', 'a.txt')将解析相对于当前目录的路径,因此此行只有在您在tm目录中时才能找到该文件 - 安装软件包后,情况几乎不会如此。您需要正确解析路径,例如针对__file__属性:

    os.path.join(os.path.dirname(__file__), '..', 'mesa', 'a.txt')
    

附加说明:

  1. 您可以安全地将py_modules=['tm.test2']替换为packages=['tm'],并且在向包中添加更多模块时无需关心更新py_modulestm
  2. setuptools提供了一个名为pkg_resources的模块,该模块为通过package_data安装的非python文件提供了有用的管理功能。例如

    open(os.path.join('..', 'mesa', 'a.txt'), 'r').read()
    

    可以替换为

    pkg_resources.resource_string('tm', '../mesa/a.txt')
    

    如果您想了解更多信息,请参阅setuptools文档中的资源管理器 API 部分。

当我处理调用不同文件夹中其他文件的文件时,我在文件顶部使用此代码。

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

然后

from file_name import value 

最新更新