I have a problem with how pip/setuptools is installing my package. When installing from the project directory (i.e. pip install .) my project's sub-packages are duplicated and placed in the root site-packages directory. The configuration is set entirely within pyproject.toml (with a minimal setup.py for compiling a single extension).
If my package is named mypackage which contains 3 sub-packages and depends on 3 dependencies, this is the expected directory structure under site-packages in the venv:
site-packages
- dependency1
- dependency2
- dependency3
- myproject
- subpackage1
- subpackage2
- subpackage3
Yet below is what I end up with, it looks like any folder containing any .py files are copied to root site-packages (i.e. including the venv itself and docs since they contain py files:
site-packages
- dependency1
- dependency2
- dependency3
- mypackage
- subpackage1
- subpackage2
- subpackage3
- subpackage1
- subpackage2
- subpackage3
- docs
- venv
What can I do to avoid duplicating sub-packages into the top-level site-packages directory/install correctly?
Here is my project structure:
myproject/
- pyproject.toml
- setup.py
- docs/
- myproject/
- __init__.py
- subpackage1/
- subpackage2/
- subpackage3/
- venv/
The reduced contents of pyproject.toml
[project]
name = "myproject"
requires-python = ">= 3.7"
dependencies = [
"dependency1",
"dependency2",
"dependency3",
]
[tool.setuptools]
packages = [
"myproject",
"myproject.subpackage1",
"myproject.subpackage2",
"myproject.subpackage3",
]
[build-system]
requires = ["setuptools >= 61.0.0", "cython"]
build-backend = "setuptools.build_meta"
The contents of setup.py:
from setuptools import Extension, setup
from Cython.Build import cythonize
ext_modules = [
Extension(
"subpackage1.func",
["..."],
extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp'],
)
]
setup(ext_modules=cythonize(ext_modules))
I've just ran into the same issue.
In my case, the build directory used by pip was polluted with the "subfolders", probably because of a previous run where my package discovery settings were erroneous.
Because of this, although my configuration was (now) correct, these orphaned directories were copied to my site-packages as well.
In my case the build directory was in the folder where I called pip install . from.
If you want to find the build directory, or just check whether this is the problem, log pip's output to a file with pip install . --log foo.txt, and search for copying inside.
You should see a line like:
Arguments: ('copying', '<build directory>\\lib\\subpackage1\\bar.py', ...
Hope this helps!
Related
I'm new to a python, I tried to build a package and faced this problem:
`Package structure:
package
- package_name
-- alembic
--- ...
-- backups
--- ...
--alembic.ini
-- __init__.py
-- some .py files
- tests
- manifest.in
- pyproject.toml
- setup.py`
I registred package in manifest:
graft package_name
setup.py looks like that
setup(
packages=["package_name"],
package_dir={
"package_name": "./package_name",
},
include_package_data=True
)
I'm using setuptools==61.0
After building I got all the files in SOURCES.txt in egg-info but after uploading package to nexus and installing I got only:
- package_name
- __init__.py
- some *.py files
in dist-info there is no files that was included in SOURCES.txt
I need to get package with alembic and backups in it. What else can I do to make this work?
I am using setuptools to create a python package. This is the directory structure:
mypackage
.git
__init__.py
pyproject.toml
setup.cfg
module1.py
module2.py
I have this structured in a flat hierarchy so I can clone this repository/copy this directory into a parent project/repository and directly write from mypackage import something, instead of having to pip install or play around with PYTHONPATH.
What do I specify in the setup.cfg file, such that this is installed as a single package, given the file structure?
# setup.cfg
[options]
package_dir = # What is here?
I tried out the custom discovery options in setuptools, which seems to work. I have to manually specify the root directory for packages. However setuptools fails when it finds multiple top-level modules/packages. So I have to use the find option to explicitly include discovered modules into a single package.
[options]
# Use the find function to find modules/packages
packages = find:
# The root directory is the current directory, relative to setup.cfg
packages_dir =
.
[options.packages.find]
# Options for the find command. Include is implicitly looking for all .py files,
# where the directory is "."
where = .
I have a problem when trying to install a Python package that I have created.
The package includes a bitmap images which is used within the package (for OCR).
My folder structure is the following:
mypackage
- mypackage
- media
- template.bmp
- module1.py
- module2.py
- etc...
- tests
- MANIFEST.in
- setup.py
template.bmp is used by the module1.py.
The MANIFEST.in file:
include mypackage/media/template.bmp
The setup.py:
setup(
....
packages = find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
include_package_data=True,
package_data={'mypackage': ['media/template.bmp']},
...
)
When I run
python setup.py sdist
I can verify that the media folder is included along with template.bmp in the .egg file. However, when referencing the bitmap in a module using
directory = os.path.dirname(os.path.abspath(__file__))
template_path = directory + '/media/template.bmp'
cv2.imread(template_path, 0)
I get a file not found error. The directory variable is the following:
'C:\\anaconda3\\lib\\site-packages\\mypackage-0.0.1-py3.6.egg\\mypackage'
Am I missing something?
Using pkg_resources solved my problem.
template_path = pkg_resources.resource_filename(__name__, '/media/template.bmp')
So I have made a small application that I typically want to package and share it with the world. I read the tutorials for packaging my app using setuptools. It was going well until I got stuck at one place.
My directory structure is something like this:
- MyApp
- setup.py
- README.md
- LICENSE.txt
- MANIFEST.in
- myapp
- __init__.py
- index.py
- utils
- __init__.py
- helper.py
- some_dump.pickle
- images
- folder_1
- image_1.jpg
- image_2.jpg
- folder_2
- another_image_1.jpg
- another_image_2.jpg
- sounds
- sound_1.wav
- sound_2.wav
Given this directory structure, I have created the setup.py file with the packages option as the list containing myapp and myapp.utils. I have also created a MANIFEST.in file that will have all the files that I want to package but which are not included by default. Here is the content of the manifest file:
include README.md
include LICENSE.txt
include myapp/utils/*.pickle
include myapp/utils/sounds/*.wav
include myapp/utils/images/folder_1/*.jpg
include myapp/utils/images/folder_2/*.jpg
The problem is that all these files are created as required in the distribution package (.zip), but when I try to use the distribution package to try the install the package myself, I don't see the images, sounds or the pickle file.
i.e. when I run python setup.py install, I don't see these files in the build/lib folder. I am not sure what the reason is. Could anyone help me out with this?
Thanks
The manifest is about distribution, not about installation.
You need to specify in setup.py what to install and WHERE:
setup(...,
data_files=[(whereto1, [file1, file2]),
(whereto2, [file3])]
)
See http://docs.python.org/3/distutils/setupscript.html#installing-additional-files
Project tree:
$.
├── happy_birthday-art.txt
├── happy_birthday.py
├── MANIFEST.in
├── README.rst
└── setup.py
setup.py
from setuptools import setup
setup(
name='Happy_birthday',
py_modules=['happy_birthday'],
data_files=['happy_birthday-art.txt'],
entry_points={
'console_scripts': ['happy_birthday = happy_birthday:main', ],},
long_description=open('README.rst').read(),
)
Now when I do python setup.py sdist and then pip install the created .tar.gz file in a virtual environment I get the following message:
warning: install_data: setup script did not provide a directory for 'happy-birthday-art.txt' -- installing right in '/home/username/.virtualenvs/happy_birthday'
The program uses that .txt file so it fails when trying to run it afterwards.
But I don't want to install happy_birthday-art.txt into a separate folder. I want to install it in the folder where happy_birthday.py is installed. Also, I don't want to have to use absolute paths in setup.py. How do I best set up my setup.py file?
If you have a single-file module like this, no folder will be created, your .py file will be moved directly into the directory which contains the other python modules (/usr/lib/pythonX.X/site-packages/, for example). That's why you have to create a directory:
$ .
|-- happy_birthday/
|-- __init__.py
|-- art.txt
|-- MANIFEST.in
|-- README.rst
|-- setup.py
http://docs.python.org/2/distutils/setupscript.html
"You can specify the data_files options as a simple sequence of files
without specifying a target directory, but this is not recommended,
and the install command will print a warning in this case. To install
data files directly in the target directory, an empty string should be
given as the directory."
However, here the target directory is NOT the site-packages folder, but the
prefix folder, that is the root of the venv. If you'd want the .txt reside in the site-packages dir bare, then it would look not only ugly but seem that really not supported. On the other hand it is possible to install it to another location in the env, for example in "share/doc/foo":
data_files=[('share/doc/foo', ['happy_birthday-art.txt'])],