Page Nav

HIDE

Breaking News:

latest

Ads Place

Build and Distribute a Python Package Using venv and PyPI

https://ift.tt/2nKLuSo Photo by Leone Venter on  Unsplash Python is an open source platform and is built on the backs of countless paid...

https://ift.tt/2nKLuSo
Photo by Leone Venter on Unsplash

Python is an open source platform and is built on the backs of countless paid and freelance developers. Its flexibility and reusable code is best leveraged when coding in an object-oriented programming (OOP) style. When we create classes, functions that can be repurposed and reused multiple times, we are exhibiting OOP. Probably the best example of the classes is implemented in Python packages.

When developing a python package, it is always good to ask yourself, ‘Who will or could benefit from this code being made user-friendly and readily accessible?’ The answer is often lots, especially if it is a commonplace repetitive task implemented in broad applications and represents an issue faced by other programmers or less mathematically inclined lay users.

Step 1: Sign up for account on pypi.org

Sign up for an account on: https://pypi.org/ . The Python Package Index (PyPI) is a repository of software for the Python programming language

Step 2: Upgrade pip version

python3 -m pip install --upgrade pip

Step 3: Configure your environment

Ideally, you develop your package in a package specific environment. So once you have navigated to a folder destination package_name/, you will run the command below. We do this, so we have a blank slate to install needed dependencies in a clean working environment. After navigating to the folder where you will ultimately be creating your package. We can use the command:

python3 -m venv env

This will create a folder inside your existing working directory called ‘env’ that represents your environment.

If you are working in VS Code (highly recommended) then you can select this environment by hitting Ctrl+ shift+ P (PC) or Cmd+ shift+ P (Mac) and selecting ‘Select interpreter’, and select your virtual env from the drop-down.

Step 4: File Structure

The generate file structure of your package should resemble something along the lines of:

package_name/
├── LICENSE
├── setup.cfg
├── setup.py
├── README.md
├── MANIFEST.in
├── env/
├── package_name/
│ ├── __init__.py
│ └── example.py
└── tests/
│ ├── __init__.py
└── └── tests.py/

So let’s walk through the creation of the next several files listed above.

__init__.py

Your __init__.py file should be empty and is used to let python know you are using a class as it helps initialize it. You can opt to put some package dependencies in here, but, most should run in the example.py file proper. You will need one __init__.py per subfolder in your package. So if you have more sub-packages you will have more __init__.py files in each corresponding folder.

README.md

This should be an informative markdown file. It provides the user information on how to use the package. This will eventually debut on your homepage on pypi.org. You can see my example here: https://pypi.org/project/psmpy/. It is best to keep this informative and as oriented to use case as possible.

Setup.py file

You do not need a static setup.cfg AND a setup.py either will work. So pick one or the other. A setup.cfg is technically preferred.

  • setup.cfg = static setup file
  • setup.py = dynamic setup file

Here is an example of a setup.py (dynamic file):

from pathlib import Path
from setuptools import find_packages, setup
dependencies = ['matplotlib', 'numpy', 'pandas',
'seaborn', 'sklearn', 'scipy', 'sklearn']
# read the contents of README file
this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text()
setup(
name='example-package',
packages=find_packages(),
version='0.0.1',
description='Propensity score matching for python and graphical plots',
author='Author name here',
author_email='author@example.com',
long_description=long_description,
long_description_content_type='text/markdown',
license='MIT',
project_urls={
"Bug Tracker": "https://github.com/",
},
classifiers=[
"Programming Language :: Python :: 3.6",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
install_requires=dependencies,
setup_requires=['pytest-runner'],
tests_require=['pytest==4.4.1'],
test_suite='tests',
)

And an example of a setup.cfg (static) file:

[metadata]
name = example-package
version = 0.0.1
author = Example Author
author_email = author@example.com
description = A small example package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/pypa/sampleproject
project_urls =
Bug Tracker = https://github.com/pypa/sampleproject/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent

[options]
package_dir =
= src
packages = find:
python_requires = >=3.6

[options.packages.find]
where = package_name

Licensing

Here is an example of an MIT license (which is most likely what you’d need). There are other options available — https://choosealicense.com/ [2]. Here is an example of a MIT license used in my own work:

Copyright (c) 2022 Author name
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

MANIFEST.in

Here is where you will list all the extra files to include in your package distribution. This will ensure your license.txt and README.md will be downloaded and installed with your package by end users.

include LICENSE
include README.md

example.py

Here is where you will build your class. You can pull in other functions, subpackages, and libraries here.

from .functions import cohenD
import numpy as np
from scipy.special import logit, expit
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LogisticRegression
import math
import pandas.api.types as ptypes
import seaborn as sns
sns.set(rc={'figure.figsize': (10, 8)}, font_scale=1.3)
class PsmPy:
"""
Matcher Class -- Match data for an observational study.
Parameters
----------
data : pd.DataFrame
Data representing the treated group
treatment : str
Column representing the control group
indx : str
Name of index column
exclude : list (optional)
List of variables to ignore in regression/matching.
target : str (optional)
Outcome variable of interest, will ignore in regression/matching
----------
"""
def __init__(self, data, treatment, indx, exclude=[], target='outcome'):
# variables generated during matching
# assign unique indices to test and control
self.data = data.dropna(axis=0, how="all") # drop NAN rows
.
.
.

Step 5. Building your package

Before building your wheels and distributions, you will need to change your virtual environment venv back to your base environment. You’ll need to install twine. Twine is a utility for publishing Python packages to PyPI. It provides builds for source and binary distributions [3].

(base) $ pip install twine

Create a source and wheel distribution:

source — a distribution package which is mostly the source code
wheel — a distribution package which has been processed to make it faster to install

sdist = source distribution
bdist_wheel = wheel distribution

(base) $ python setup.py sdist bdist_wheel

This will add a dist folder to your directory:

package_name/
├── LICENSE
├── setup.cfg
├── setup.py
├── README.md
├── venv/
├── dist/
│ ├── package_name-0.1.0-py3-none-any.whl
│ ├── package_name-0.1.0.tar.gz
├── build
├── package_name.egg-info
├── package_name/
│ ├── __init__.py
│ └── example.py
└── tests/

Step 6: Uploading/distributing your package

Upload your package to PyPI with the command: twine upload dist/*. You will be prompted for your username and password created earlier!

(base) $ twine upload dist/*
Uploading distributions to https://upload.pypi.org/legacy/
Enter your username: YOUR_USER_NAME
Enter your password: YOUR_PASSWORD
Uploading package_name-0.1.0.tar.gz
100%|██████████████████████████████████████████████████████████████| 2.5k/2.5k [00:01<00:00, 2.1kB/s]

You can also upload your distributions to TestPyPI for testing (optional):

(base) $ twine upload -r testpypi dist/*

You can now install your own package from pypi.org by the pip command. Please note as you make updates to your package you will need to change the version number, otherwise the upload to pypi.org will not work.

Image by author

Happy creating!

References

[1]Packaging Python Projects, https://packaging.python.org/en/latest/tutorials/packaging-projects/, accessed: April 11th 2022
[2]Choose an open source license, https://choosealicense.com/ accessed: April 13th 2022
[3]Twine, https://pypi.org/project/twine/ accessed: April 13th 2022


Build and Distribute a Python Package Using venv and PyPI was originally published in Towards Data Science on Medium, where people are continuing the conversation by highlighting and responding to this story.



from Towards Data Science - Medium https://ift.tt/a2SqlC5
via RiYo Analytics

No comments

Latest Articles