如何正确分配带有数据文件的pip包?

Fom*_*aut 5 python pip setup.py python-3.x

我有以下软件包要分发:

mymodule/
    data/
        1.txt
    mymodule/
        __init__.py
    tests/
        test_mymodule.py
    setup.py
Run Code Online (Sandbox Code Playgroud)

为了在vitualenv下安装它,我应用以下命令:

pip install .
Run Code Online (Sandbox Code Playgroud)

一切都安装正确,但我的数据文件的路径已损坏。

>>> from mymodule import get
>>> print(get())
...
FileNotFoundError: [Errno 2] No such file or directory: '/home/alexander/Stuff/pip_example/mymodule_test/venv/lib/python3.5/site-packages/mymodule/../data/1.txt'
Run Code Online (Sandbox Code Playgroud)

经过研究发现,该文件夹data是在导致错误的virtualenv文件夹的根目录中创建的。我应该如何改进代码以保持测试正常工作并拥有正确的数据文件路径?

文件内容:

数据/1.txt

yes
Run Code Online (Sandbox Code Playgroud)

mymodule / __ init__.py

import os

src = os.path.join(
    os.path.dirname(__file__),
    '../data/1.txt'
)

def get():
    with open(src) as f:
        return f.read().strip()
Run Code Online (Sandbox Code Playgroud)

测试/ test_mymodule.py

import unittest
import mymodule

class MymoduleTest(unittest.TestCase):
    def test_get(self):
        s = mymodule.get()
        self.assertEqual(s, "yes")
Run Code Online (Sandbox Code Playgroud)

setup.py

from distutils.core import setup

data_files = [
    ('data', ['data/1.txt'])
]

setup(
    name='mymodule',
    version='0.0',
    packages=['mymodule'],
    data_files=data_files,
)
Run Code Online (Sandbox Code Playgroud)

我是包装Python模块的新手。请帮我解决这个问题。

================================================== ===================

我发现我需要使用它sys.prefix来访问virtualenv的根目录。换句话说,如果我以这种方式编辑mymodule.__init__.py,那么一切将正常工作:

import os
import sys

src = os.path.join(sys.prefix, 'data/1.txt')

def get():
    with open(src) as f:
        return f.read().strip()
Run Code Online (Sandbox Code Playgroud)

但是之后,测试失败并显示以下错误:

FileNotFoundError: [Errno 2] No such file or directory: '/usr/data/1.txt'
Run Code Online (Sandbox Code Playgroud)

这是因为sys.prefix/usr没有被激活的virtualenv。我想,所以我需要一种不同的方法来改善包装。

Pie*_*uyl 2

  1. 安装软件包时检查您的文件是否已正确分发。

  2. sys.prefix不会找到“你的”包裹。模块的属性__file__指向文件__init__.py。您可以将其用作基本路径,如下所示:

    import os
    import mymodule
    
    src = os.path.join(os.dirname(mymodule.__file__), 'data/1.txt')
    
    def get():
        with open(src) as f:
            return f.read().strip()
    
    Run Code Online (Sandbox Code Playgroud)

  • 您可以使用 distutils 来做到这一点(请参阅[文档](https://docs.python.org/3.5/distutils/setupscript.html#installing-additional-files)),但 setuptools 是现在推荐的工具,对于 setuptools 来说它是[不可能](https://setuptools.readthedocs.io/en/latest/setuptools.html#non-package-data-files)。 (2认同)