setup.py sdist 排除子目录中的包

31

我有以下的项目结构,希望能够打包:

├── doc
│   └── source
├── src
│   ├── core
│   │   ├── config
│   │   │   └── log.tmpl
│   │   └── job
│   ├── scripts
│   └── test
└── tools

我希望把core打包到src下,但排除test。这是我不成功的尝试:

      setup(name='core',
      version=version,  
      package_dir = {'': 'src'}, # Our packages live under src but src is not a package itself
      packages = find_packages("src", exclude=["test"]), # I also tried exclude=["src/test"]
      install_requires=['xmltodict==0.9.0',
                        'pymongo==2.7.2',
                        'ftputil==3.1',
                        'psutil==2.1.1',
                        'suds==0.4',
                        ],
      include_package_data=True,
      )

我知道可以使用MANIFEST.in文件来排除test, 但如果您能向我展示如何使用setupfind_packages来实现这一点,我会很高兴。

更新:

经过一些尝试,我意识到使用python setup.py install构建软件包会产生我期望的结果(即,排除test)。然而,使用python setup.py sdist会导致所有东西都被包括在内(即,它忽略了我的排除指令)。我不知道这是一个bug还是一个特性,但仍然有可能使用MANIFEST.in排除sdist中的文件。


test 是 Python 包还是只是一个包含顶级 Python 脚本的目录? - jfs
它是一个Python包(例如,它在其中有一个__init__.py文件)。 - oz123
在Python控制台中分析setuptools.find_packages方法,我们可以发现该方法返回收集的基础包及其子包。 exclude ='test'确切地删除了顶级包,但该方法将返回test的子包。 正确的值可能是exclude = ['test','test.*'] - alexzshl
我也遇到了同样的问题,setuptools.find_packages无法排除我想要排除的包,但是MANIFEST.in可以帮助解决这个问题。 - Levin
4个回答

45

find_packages("src", exclude=["test"]) 能够正常工作。
关键是要删除陈旧的文件,例如 core.egg-info 目录。 在您的情况下,您需要删除 src/core.egg-info

这是我使用的 setup.py

from setuptools import setup, find_packages

setup(name='core',
      version='0.1',
      package_dir={'':'src'},
      packages=find_packages("src", exclude=["test"]), # <- test is excluded
      ####packages=find_packages("src"), # <- test is included
      author='J.R. Hacker',
      author_email='jr@example.com',
      url='https://dev59.com/_F8d5IYBdhLWcg3wsT0b',
      package_data={'core': ['config/*.tmpl']},
)

要创建分发版本,请运行:

$ python setup.py sdist bdist bdist_wheel

要启用后续命令,请运行:pip install wheel

我已经检查了创建的文件。它们不包含test,但包含core/__init__.pycore/config/log.tmpl文件。


1
这个技巧真的很有效。我在你的答案中强调了这一点。这确实是一个错误,即这个陈旧的文件没有被每次重新创建。 - oz123
@Oz123:你可以尝试在setuptools的mercurial存储库中提交错误报告。关于clean --all,这里也有一个相关但不同的问题issue about clean --all - jfs
1
这在2017年还是个bug吗?!我在setuptools 35.0.2中遇到了这个问题!我通过修改我的setup.py脚本来解决,删除了<package-name>.egg-info/文件夹,但我很惊讶这个问题还没有被解决。我错过了什么吗? - farenorth
@farenorth:我已经尝试过使用setuptools 36.0.1,但你仍然需要使用之前的setup.py版本创建一些构件--这在实践中是很常见的--有些错误只有通过干净的构建才能消失。 - jfs
@Oz123:这个答案在没有通配符的情况下是有效的。如果你认为bh4r4th的答案(带有通配符)更适合你的问题,你可以改变接受的答案。 - jfs
显示剩余2条评论

12
在项目根目录下的MANIFEST.in中添加。
prune src/test/

然后使用python setup.py sdist构建软件包。


1

我可能只是使用 find_packages 文档中定义的通配符。 *test**tests* 是我倾向于使用的,因为我们仅保存带有单词 test 的测试文件名。简单易行 ^-^。

setup(name='core',
  version=version,  
  package_dir = {'': 'src'}, # Our packages live under src but src is not a package itself
  packages = find_packages("src", exclude=['*tests*']), # I just use wild card. Works perfect ^-^
  install_requires=['xmltodict==0.9.0',
                    'pymongo==2.7.2',
                    'ftputil==3.1',
                    'psutil==2.1.1',
                    'suds==0.4',
                    ],
  include_package_data=True,
  )

提示:

我建议将以下内容添加到 .gitignore 文件中。

build
dist
pybueno.egg-info

将构建、打包和推送软件包到pypi或您的私有仓库,整合到CI/CD中,使整个设置看起来干净整洁。

0
假设您的文件夹名为 tests 而不是 test,则以下代码应该可以正常工作:
  setup(name='core',
  version=version,  
  package_dir = {'': 'src'}, # Our packages live under src but src is not a package itself
  packages = find_packages('src', exclude=['tests'])
  install_requires=['xmltodict==0.9.0',
                    'pymongo==2.7.2',
                    'ftputil==3.1',
                    'psutil==2.1.1',
                    'suds==0.4',
                    ],
  include_package_data=True,
  )

1
这个不起作用。我的源代码中包含了测试或测试目录。 - oz123
像ssalentin一样,我对你的例子中不一致使用“test”和“tests”感到困惑,@Oz123(并提交了一个编辑,在其中始终使用“test”)。你的评论也让我感到困惑。你是指你的源代码可能包含名为“test”或“tests”的目录,并且你想捕获这两种可能性吗?还是你的意思是无论你在排除参数中指定“test”还是“tests”,这些目录都被包括在内?如果你想捕获多个可能性,你需要使用通配符。 - Alan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接