How to upload pylib to PyPi
Step1: Pypi and TestPypi account
Click link to register Pypi and TestPypi account.
These two accounts need to register seperately. The Pypi account if for official library upload and the test one is for library testing.
I strongly recommend to upload your library to TestPypi and use it first before you upload it to the official Pypi.
Step2: Setup environment
Need to install setuptools
, wheel
, twine
using the following commands:
pip install setuptools wheel twine
To save your time, you can just use anaconda to install the following environment.yml
:
name: pipenv
channels:
- defaults
dependencies:
- pip==21.1.2
- python==3.7.11
- pip:
- setuptools
- wheel
- twine
Using the following command in your terminal to create a new pipenv
virtual environment:
conda env create -f environment.yml
Step 3: Construct files
3.1 Overall structure
project_name
.
├── LICENSE
├── README.md
├── setup.py
├── package_name
│ ├── __init__.py
│ ├── main.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── utils.py
│ │ └── example
│ ├── __init__.py
├── tests
│ ├── __init__.py
│ └── example
│ ├── __init__.py
You can make your structure like above but you need to have some necessary files, which I will introduce one by one.
Here is my example that you can refer to: MiSTGen
3.2 License
Each package you uploaded to PyPi requirs a license.
To choose your license:
- Find it in this website: https://choosealicense.com/
- Or pick one when you create your Github repo
Your license should be included in a LICENSE
file in the root directory.
3.3 Setup.py
setup.py
is the build script for setuptools. It tells setuptools your package (such as name and version) and the code files to include.
#!/usr/bin/env python
from setuptools import setup, find_packages
import package_name
with open("README.md", "r", encoding='utf-8') as fh:
long_description = fh.read()
setup(
name="lib_name",
version=package_name1.__version__,
author="Your name",
author_email="Your email",
description="A short description",
long_description=long_description,
long_description_content_type="text/markdown",
license="Your selected license",
url="Your github url",
packages=find_packages(),
install_requires=[
"matplotlib==3.4.2",
"numpy",
"cvxopt"
],
classifiers=[
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
],
)
-
name
is your library name, search on PyPi to avoid any “same name” conflict. -
version
is your version number, when you upload your package, make sure the lastest version is higher than previous version. Here I put it in thepackage_name/__init__.py
file. You can also put some necessary info in this file, just like me:__title__ = 'package_name' __version__ = '0.1.0' __author__ = 'Author_names' __copyright__ = 'Copyright 2022 author_names'
-
description
is a short description. -
long_description
is a long description, you can use what every you put into yourREADME.md
file. -
url
is your project url address, you can put your github_url here. -
packages
is your package list.setuptools.find_packages()
will automatically final all your packages under root directory. Here you have only one packagepackage_name
. -
install_requires
contains all the dependencies that this library is needed to run. -
classifiers
is written based on PyPi Classifiers, it contains at least your using python version. - For more details, please check Packaging Python Projects
Step 4: Build program
Run following command in root directory which is where setup.py
located.
- To check and see if your
setup.py
file is correct:
python setup.py check
you should be able to see: running check
if there is no errors.
- Build program:
python setup.py sdist bdist_wheel
After you build your program(step 4), you will see two files in the build
directory of your root directory: one is xxx.tar.gz
file, which is your source file, and the other one is your distribution xxx.hl
file.
Step 5: Upload
To upload your package to the PyPi and TestPyPi, we need to setup our configuration file first to prevent constantly input our username and password everytime. (I’m a lazy person so I’ll only introduce the lazy way, lol)
5.1 Set up your local pypirc file
Inorder to make your upload easier and save the time of inputing user name and password, create a .pypirc
in your home directory:
- Windows: that would normally be
C:\\User\Username\
- Linx: put
.pypirc
under~/
directory.
What you need to modify in your .pypirc
would be your user name and password.
[pypi]
repository = https://upload.pypi.org/legacy/
username = (your user name)
password = (your password)
[testpypi]
username = (your user name)
password = (your password)
5.2 Upload your package
- To upload to the PyPi:
twine upload dist/*
- Before you do the above step, I strongly recommend you to upload your package to TestPyPi first:
twine upload --repository testpypi dist/*
Caveat:
- TestPyPi is just for testing if you can upload your project correctly, but it cannot be used as the really pip install packages for you to test since if you have multiple packages install require in your
setup.py
file, likematlibplot
, TestPyPi website may not have this package and correct version for your test package to install and you will see something like:
ERROR: Could not find a version that satisfies the requirement matplotlib (from opencoodx) (from versions: none)
ERROR: No matching distribution found for matplotlib
- To test the function of your package, you still need to upload your package to PyPi
Step6: How to use
After you publish toPyPi or TestPyPi , you should be able to install it useing the command:
- For testing
pip install -i https://test.pypi.org/simple/ your_lib_name
- For
official
pip install your_lib_name
Here is my example: mistgen
Some other problems
Q1: How to include non-python files in your tar.gz file?
When you open your xxx.tar.gz
file, you will find other are some data files (.txt
, .yml
,.yaml
) or other program files like (.pyx
, .pyd
) are not in your source file. You can create a MANIFEST.in
or setup.cfg
your root directory:
project_name
.
├── LICENSE
├── README.md
├── setup.py
├── setup.cfg
├── MANIFEST.in
├── package_name
In the MANIFEST.in
, you can write the following:
global-include *.pyx
Then you will include all the .pyx
in your package, but this will be very slow since it will traverse all the package files.
Or you could just include some specific directory or file, like this:
include package_name/package_data/*
include package_name/utils/abc.pyx
Then you will include everything inside package_data
directory and abc.pyx
file in the utils
directory.
In this way, you can include any non-python(.py) files into your source file.
Q2: How to include non-python files in your whl file?
When people use pip install your_package_name
to install your python package, this command will download everything in your .whl
file.
Even after you specify everything you want to include in the MANIFEST.in
, your .whl
file still doesn’t have those non-python files that you need, like data files (.txt
, .yml
,.yaml
) or other program files like (.pyx
, .pyd
).
In this case, you need to modify your setup.py
like following:
setup(
...
package_data={"":["*.yaml","*.pyx"]},
)
In this way, you can then include all the .yaml
and .pyx
files into your distribution whl
file.
for more details, you can check here
Reference
- https://packaging.python.org/en/latest/guides/using-testpypi/
- https://packaging.python.org/en/latest/tutorials/packaging-projects/
- https://blog.csdn.net/MemoryD/article/details/84295855
- https://towardsdatascience.com/how-to-upload-your-python-package-to-pypi-de1b363a1b3
- https://packaging.python.org/en/latest/guides/using-manifest-in/
- https://setuptools.pypa.io/en/latest/userguide/package_discovery.html
- https://setuptools.pypa.io/en/latest/userguide/datafiles.html
Enjoy Reading This Article?
Here are some more articles you might like to read next: