I'm testing a trivial installable package with Python setuptools. I have read a handful of tutorials and official documentation, so I thought I had a good background. It seems I was wrong.
The minimal package I'm playing with has the following structure:
myapp
├── config
│ └── text.txt
├── MANIFEST.in
├── myapp
│ ├── __init__.py
│ ├── lib.py
│ └── __main__.py
└── setup.py
With the following contents:
__init__.py (this is just to make the package usable as a library when imported):
import myapp.lib
__main__.py (I want to make this application basically runnable from the terminal with -m
or better, with an entry point):
import sys
import myapp
import myapp.lib
def main():
print("main function called")
print(f"current path: {sys.path}")
myapp.lib.funct()
if __name__ == "__main__":
main()
myapp/lib.py (this is the module with the logic, and it relies on external data):
from pathlib import Path
textfile = Path(__file__).parent.parent / 'config/text.txt'
def funct():
print("hello from function in lib")
with open(textfile, 'r') as f:
print(f.read())
config/text.txt (this is the data):
some text constant as part of the module
To package this module, I have crafted the following setup.py
setup(
name="myapp",
version="1.0.0",
description="A simple test",
author="me",
url='www.me.com',
author_email="me@email.com",
classifiers=[
"Programming Language :: Python :: 3",
],
packages=["myapp"],
include_package_data=True,
entry_points={"console_scripts": ["myapp=myapp.__main__:main"]},
)
As well as a MANIFEST.in file:
include config/*
OK, these are the ingredients. Now, I create a distribution with python setup.py sdist
. This creates a file dist/myapp-1.0.0.tar.gz
, which does include the data file (along with plenty of metadata I don't fully understand):
> tar tf myapp-1.0.0.tar.gz
myapp-1.0.0/
myapp-1.0.0/MANIFEST.in
myapp-1.0.0/PKG-INFO
myapp-1.0.0/config/
myapp-1.0.0/config/text.txt
myapp-1.0.0/myapp/
myapp-1.0.0/myapp/__init__.py
myapp-1.0.0/myapp/__main__.py
myapp-1.0.0/myapp/lib.py
myapp-1.0.0/myapp.egg-info/
myapp-1.0.0/myapp.egg-info/PKG-INFO
myapp-1.0.0/myapp.egg-info/SOURCES.txt
myapp-1.0.0/myapp.egg-info/dependency_links.txt
myapp-1.0.0/myapp.egg-info/entry_points.txt
myapp-1.0.0/myapp.egg-info/top_level.txt
myapp-1.0.0/setup.cfg
myapp-1.0.0/setup.py
Now, the problem comes when I try to install the package with pip install myapp-1.0.0.tar.gz
. It does not copy the config/text.txt
anywhere. In my site-packages
folder, I see the directories myapp
and myapp-1.0.0.dist-info
, but there is no text file inside any of them.
There are various things I don't understand:
- is the definition of
textfile
in myapp/lib.py correct/sensible? I mean, I find it cumbersome and almost like I'm hardcoding this, having to use a module on purpose to build a simple path to this data file. I feel I'm overdoing this, but I have not found this part of the packing step very well documented. It's surprising, as this must be a very common problem. - given the the data file IS in the tar file. Why did
pip
not copy it tosite-packages
? - what is this
myapp-1.0.0.dist-info
folder in mysite-packages
?