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.
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