python - 如何从 `src/`目录下的python包访问项目根目录中的文本文件

标签 python versioning setuptools setup.py pkg-resources

我希望我的包的版本号位于一个地方,所有需要它的地方都可以引用它。

我在这份关于 Single Sourcing the Package Version 的 Python 指南中找到了一些建议并决定尝试 #4,将其存储在我的项目根目录中名为 VERSION 的简单文本文件中.

这是我的项目目录树的简化版本(您可以看到 the full project on GitHub ):

.
├── MANIFEST.in
├── README.md
├── setup.py
├── VERSION
├── src/
│   └── fluidspaces/
│       ├── __init__.py
│       ├── __main__.py
│       ├── i3_commands.py
│       ├── rofi_commands.py
│       ├── workspace.py
│       └── workspaces.py
└── tests/
    ├── test_workspace.py
    └── test_workspaces.py

VERSIONsetup.py是 sibling ,很容易读取安装脚本中的版本文件并用它做任何我想做的事。

但是VERSIONsrc/fluidspaces/__main__.py不是 sibling ,主模块不知道项目根目录的路径,所以我不能使用这种方法。

导游有这样的提醒:

Warning: With this approach you must make sure that the VERSION file is included in all your source and binary distributions (e.g. add include VERSION to your MANIFEST.in).

这似乎是合理的——不需要包模块需要项目根路径,版本文件可以在构建时复制到包中以便于访问——但我将该行添加到 list 中,版本文件似乎仍然没有出现在构建中的任何地方。

要构建,我正在运行 pip install -U .从项目根目录和 virtualenv 内部。这是在 <virtualenv>/lib/python3.6/site-packages 中创建的文件夹结果:

fluidspaces/
├── i3_commands.py
├── __init__.py
├── __main__.py
├── __pycache__/  # contents snipped
├── rofi_commands.py
├── workspace.py
└── workspaces.py
fluidspaces-0.1.0-py3.6.egg-info/
├── dependency_links.txt
├── entry_points.txt
├── installed-files.txt
├── PKG-INFO
├── SOURCES.txt
└── top_level.txt

我的更多配置文件:

MANIFEST.in:

include README.md
include VERSION
graft src
prune tests

setup.py:

#!/usr/bin/env python3

from setuptools import setup, find_packages


def readme():
    '''Get long description from readme file'''
    with open('README.md') as f:
        return f.read()


def version():
    '''Get version from version file'''
    with open('VERSION') as f:
        return f.read().strip()


setup(
    name='fluidspaces',
    version=version(),
    description='Navigate i3wm named containers',
    long_description=readme(),
    author='Peter Henry',
    author_email='me@peterhenry.net',
    url='https://github.com/mosbasik/fluidspaces',
    license='MIT',
    classifiers=[
      'Development Status :: 3 - Alpha',
      'Programming Language :: Python :: 3.6',
    ],
    packages=find_packages('src'),
    include_package_data=True,
    package_dir={'': 'src'},
    package_data={'': ['VERSION']},
    setup_requires=[
        'pytest-runner',
    ],
    tests_require=[
        'pytest',
    ],
    entry_points={
        'console_scripts': [
            'fluidspaces = fluidspaces.__main__:main',
        ],
    },
    python_requires='~=3.6',
)

我发现了这个 SO 问题 Any python function to get “data_files” root directory?这让我觉得 pkg_resources图书馆是我的问题的答案,但我一直无法弄清楚如何在我的情况下使用它。

我遇到了麻烦,因为我发现的大多数示例都直接在项目根目录中有 python 包,而不是在 src/ 中隔离目录。我正在使用 src/目录,因为这些建议:

我发现并尝试稍微转动一下的其他旋钮是 package_data , include_package_data , 和 data_files setup() 的 kwargs| .不知道他们有多相关。用这些声明的东西和 list 中声明的​​东西之间似乎有一些相互作用,但我不确定细节。

最佳答案

在 Freenode 的#python IRC channel 中与一些人讨论了这个问题。我了解到:

  • pkg_resources 可能是如何我应该按照我的要求去做,但它需要将版本文件放在包目录而不是项目根目录中。
  • setup.py 中,我可以从包目录中读取这样一个版本文件,而无需导入包本身(出于某些原因,这是一个禁忌),但它需要对路径进行硬编码从根到包,我想避免。

最终我决定使用 setuptools_scm包从我的 git 标签而不是从我的 repo 中的文件获取版本信息(其他人正在用他们的包这样做,他们的论点很有说服力)。

因此,我很容易在 setup.py 中得到了我的版本号:

setup.py:

from setuptools import setup, find_packages

def readme():
    '''Get long description from readme file'''
    with open('README.md') as f:
        return f.read()

setup(
    name='fluidspaces',
    use_scm_version=True,  # use this instead of version
    description='Navigate i3wm named containers',
    long_description=readme(),
    author='Peter Henry',
    author_email='me@peterhenry.net',
    url='https://github.com/mosbasik/fluidspaces',
    license='MIT',
    classifiers=[
      'Development Status :: 3 - Alpha',
      'Programming Language :: Python :: 3.6',
    ],
    packages=find_packages('src'),
    package_dir={'': 'src'},
    setup_requires=[
        'pytest-runner',
        'setuptools_scm',  # require package for setup
    ],
    tests_require=[
        'pytest',
    ],
    entry_points={
        'console_scripts': [
            'fluidspaces = fluidspaces.__main__:main',
        ],
    },
    python_requires='~=3.6',
)

但我最终不得不有一个硬编码路径来指示相对于包代码的项目根应该是什么,这是我之前一直避免的。我想this issue on the setuptools_scm GitHub repo可能就是为什么这是必要的。

src/fluidspaces/__main__.py:

import argparse
from setuptools_scm import get_version  # import this function

def main(args=None):
    # set up command line argument parsing
    parser = argparse.ArgumentParser()
    parser.add_argument('-V', '--version',
                        action='version',
                        version=get_version(root='../..', relative_to=__file__))  # and call it here

关于python - 如何从 `src/`目录下的python包访问项目根目录中的文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46880569/

相关文章:

python - 在 python 的字典树中搜索值

python - 如何在 Flask 的扩展名为 .jhtml 的模板中启用自动转义?

haskell - 如何列出 Cabal 计算的依赖项

python - 当 setup.py 使用 Python 版本 3 解释器运行时,如何构建 py2 wheel 包?

python - setuptools的麻烦——不包括包,包括数据文件

python - 有没有更好的方法来重写这个 NumPy 片段

python - 在 Python 中追加字典

java - CMIS 版本控制未按预期工作

ruby-on-rails - rails 4 x paper_trail : track which attributes are updated and display their new value

Python "setup.py develop"为什么我的数据包不可用?