简体   繁体   中英

How can a Python module single file be installed using pip and PyPI?

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     = "j.drake@sern.ch",
        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     = "j.drake@sern.ch",
        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     = "j.drake@sern.ch",
        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

setup.py

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.

Install Requires

The install_requires is used to define the dependencies for your module/application. For eg 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.

Entry Points

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM