I have a setup.py
file that checks if the user has setuptools
and if he doesn't, then I am forced to use distutils
. The thing is that, to make sure the submodules are installed, I use setuptools
' find package:
from setuptools import setup, find_packages
packages = find_packages()
and then proceed from there.
However, I'm not sure how to do that with distutils
. Is there an equivalent function or do I have to manually look for subdirs that have an __init__.py
inside of them? If that is the case, is it acceptable for me to require setuptools
to install my package and just forget about distutils
?
Cheers.
Most Python users will not want to use this module directly, but instead use the cross-version tools maintained by the Python Packaging Authority. In particular, setuptools is an enhanced alternative to distutils that provides: support for declaring project dependencies.
Even in a vanilla version of Python 3.7. 6 (installed via pyenv ), the packages installed by default are both pip and setuptools .
distutils has been deprecated in NumPy 1.23. 0 . It will be removed for Python 3.12; for Python <= 3.11 it will not be removed until 2 years after the Python 3.12 release (Oct 2025).
Function defined in setuptools find_packages(where='.', exclude=()) Return a list all Python packages found within directory 'where' 'where' should be supplied as a “cross-platform” (i.e. URL-style) path; it will be converted to the appropriate local path syntax.
It is perfectly acceptable to use setuptools; the vast majority of packages on PyPI already do.
If you want to re-invent the find_packages()
wheel, then yes, look for directories with __init__.py
files in them. This is what the setuptools.PackageFinder
class does. A simplified re-implementation would be:
import os
from distutils.util import convert_path
def find_packages(base_path):
base_path = convert_path(base_path)
found = []
for root, dirs, files in os.walk(base_path, followlinks=True):
dirs[:] = [d for d in dirs if d[0] != '.' and d not in ('ez_setup', '__pycache__')]
relpath = os.path.relpath(root, base_path)
parent = relpath.replace(os.sep, '.').lstrip('.')
if relpath != '.' and parent not in found:
# foo.bar package but no foo package, skip
continue
for dir in dirs:
if os.path.isfile(os.path.join(root, dir, '__init__.py')):
package = '.'.join((parent, dir)) if parent else dir
found.append(package)
return found
This ignores the include
and exclude
arguments of setuptools.find_packages()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With