I am trying to learn how to make a Python module available via pip on PyPI. In order to do this, I am testing using the PyPI test site (https://testpypi.python.org/pypi) and have attempted to create a setup.py
for the module. My module is a file at the root directory and I cannot get it to be installed successfully. I want to find out how to do this.
Below, I detail the steps I am taking. I suspect that the problem lies in how I have written setup.py
.
The anatomy of the repository is as follows:
.
├── examples_1.py
├── LICENSE
├── MANIFEST.in
├── README.rst
├── setup.py
└── supermodule.py
Note that the module is simply the file supermodule.py
at the root of the directory. Note also that the file examples_1.py
is not to be included in an installation of the module package.
The contents of setup.py
are as follows:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import setuptools
def read(*paths):
with open(os.path.join(*paths), "r") as filename:
return filename.read()
def main():
setuptools.setup(
name = "supermodule",
version = "2015.10.30.0820",
description = "super utilities",
long_description = (read("README.rst")),
url = "https://github.com/johndrake1/junk",
author = "John Drake",
author_email = "[email protected]",
license = "GPLv3",
package_data = {
"": [
"*.txt",
"*.md",
"*.rst",
"*.py"
]
}
)
if __name__ == "__main__":
main()
I go through the following procedures to register, upload and install the package:
python setup.py register -r https://testpypi.python.org/pypi
python setup.py sdist upload -r https://testpypi.python.org/pypi
sudo pip install -i https://testpypi.python.org/pypi supermodule
In the source distribution, supermodule-2015.10.30.0820.tar.gz
, I can see the following directory structure:
.
└── supermodule-2015.10.30.0820
├── LICENSE
├── MANIFEST.in
├── PKG-INFO
├── README.rst
├── setup.cfg
├── setup.py
├── supermodule.egg-info
│ ├── dependency_links.txt
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ └── top_level.txt
└── supermodule.py
So, it appears that the packaging and uploading works fine and contains the module file supermodule.py
that is at the root directory. However, when I install the package, I get the following files installed locally:
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/DESCRIPTION.rst
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/METADATA
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/RECORD
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/WHEEL
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/metadata.json
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0820.dist-info/top_level.txt
You can see that the file supermodule.py
is not there and it cannot be imported in a Python instance. What should I do to include this file in the installation such that it is importable in Python?
EDIT: Following a suggestion by @DeanFenster, I moved the file supermodule.py
to supermodule/__init__.py
and changed setup.py
to the following:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import setuptools
def read(*paths):
with open(os.path.join(*paths), "r") as filename:
return filename.read()
def main():
setuptools.setup(
name = "supermodule",
version = "2015.10.30.0902",
description = "super utilities",
long_description = (read("README.rst")),
url = "https://github.com/johndrake1/junk",
author = "John Drake",
author_email = "[email protected]",
license = "GPLv3",
packages = ["supermodule"]
)
if __name__ == "__main__":
main()
Following registration, upload and installation, this resulted in an installation that made the module importable, with the following files installed locally:
/usr/local/lib/python2.7/dist-packages/supermodule
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info
/usr/local/lib/python2.7/dist-packages/supermodule/__init__.py
/usr/local/lib/python2.7/dist-packages/supermodule/__init__.pyc
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/DESCRIPTION.rst
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/METADATA
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/RECORD
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/WHEEL
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/metadata.json
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.0902.dist-info/top_level.txt
It's good that this approach works, but I would still like to know how to install the module when it is in the form of a single file.
EDIT: Following a suggestion by @Xk0nSid, I changed setup.py
to the following:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import setuptools
def read(*paths):
with open(os.path.join(*paths), "r") as filename:
return filename.read()
def main():
setuptools.setup(
name = "supermodule",
version = "2015.10.30.1001",
description = "super utilities",
long_description = (read("README.rst")),
url = "https://github.com/johndrake1/junk",
author = "John Drake",
author_email = "[email protected]",
license = "GPLv3",
py_modules = ["supermodule"],
entry_points = """
[console_scripts]
supermodule = supermodule:supermodule
"""
)
if __name__ == "__main__":
main()
Following registration, upload and installation, this resulted in an installation that made the module importable, with the following files installed locally:
/usr/local/bin/supermodule
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info
/usr/local/lib/python2.7/dist-packages/supermodule.py
/usr/local/lib/python2.7/dist-packages/supermodule.pyc
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/DESCRIPTION.rst
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/METADATA
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/RECORD
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/WHEEL
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/entry_points.txt
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/metadata.json
/usr/local/lib/python2.7/dist-packages/supermodule-2015.10.30.1001.dist-info/top_level.txt
This approach was successful at handling the single file form of the module.
Try using something like this for a single file. Following is the directory structure:
.
├── example.py
├── LICENSE
├── README.md
└── setup.py
0 directories, 4 files
from setuptools import setup
setup(
name='example',
version='0.1.0',
py_modules=['example'],
install_requires=[
'exampledep',
],
entry_points='''
[console_scripts]
example=example:example
''',
)
The above worked for me. This is how example file would look like.
def example():
# Note: You can use sys.argv here
print "Hi! I'm a command written in python."
This can also be imported like so:
import example
example.example()
# or
from example import example
example()
Hope this helps.
The install_requires
is used to define the dependencies
for your module/application. For e.g in this case example
module in dependent on exampledep
. So when someone does pip install example
, then pip will also install exampledep
as it is listed in the dependencies.
This is usually a callable which the end user of package might want to use. This usually a callable and is used for command line. You can look at this question or this doc for more details.