How to exclude a single file from package with setuptools and setup.py

强颜欢笑 提交于 2019-12-01 05:42:01

问题


I am working on blowdrycss. The repository is here.

I want the settings file for blowdrycss_settings.py to be excluded from the final package on pypi. The intention is to dynamically build a custom settings file that will be placed in the users virtualenv / project folder.

In setup.py, I have the following:

packages=find_packages(exclude=['blowdrycss_settings.py', ]),

I also tried exclude_package_data:

exclude_package_data={
    '': ['blowdrycss_settings.py'],
    '': ['blowdrycss/blowdrycss_settings.py'],
    'blowdrycss': ['blowdrycss_settings.py'],
},

I then run python setup.py sdist bdist.

However, when I look in the build folder I still see blowdrycss_settings.py:

- build 
    - lib
        - blowdrycss_settings.py

It seems like it should be simple to just exclude a file.

How do I exclude blowdrycss_settings.py from the distributed package?


回答1:


Here is my solution.

Underneath of blowdrycss, I created a new module called settings so the directory structure now looks like this:

blowdrycss
    blowdrycss
        settings
            blowdrycss_settings.py

Based on this reference, inside of setup.py I have the following:

packages=find_packages(exclude=['*.settings', ]),   

To build the distribution:

  1. Delete the build, dist, and .egg-info folders.
  2. Run python setup.py sdist bdist

In retrospect, it is good that I was unable to do what I was originally attempting. The new structure feels cleaner and is more modular.




回答2:


Imagine you have a project

root
├── setup.py
└── spam
    ├── __init__.py
    ├── bacon.py
    └── eggs.py

and you want to exclude spam/eggs.py from packaging:

import fnmatch
from setuptools import find_packages, setup
from setuptools.command.build_py import build_py as build_py_orig


excluded = ['spam/eggs.py']


class build_py(build_py_orig):
    def find_package_modules(self, package, package_dir):
        modules = super().find_package_modules(package, package_dir)
        return [
            (pkg, mod, file)
            for (pkg, mod, file) in modules
            if not any(fnmatch.fnmatchcase(file, pat=pattern) for pattern in excluded)
        ]


setup(
    packages=find_packages(),
    cmdclass={'build_py': build_py}
)

Globs and multiple entries in excluded list will work too because it is consumed by fnmatch, so you can e.g. declare

excluded = [
    'modules_in_directory/*.py',
    'modules_in_subtree/**/*.py',
    'path/to/other/module.py'
]

etc.

This recipe is based on my other answer to the question setup.py exclude some python files from bdist . The difference is that this recipe excludes modules based on file globs, while the other one excludes modules based on qualnames, for example

excluded = ['spam.*', '*.settings']

will exclude all submodules of spam package and all modules named settings in every package and subpackage etc.



来源:https://stackoverflow.com/questions/35115892/how-to-exclude-a-single-file-from-package-with-setuptools-and-setup-py

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!