Python Project Management - Pypi Upload
Contents
0. Purpose
The purpose of this blog is to show just simplified version of how to start developing python project upload it to pypi. When I googled, I found that there are many ways to to, but many of them are ambigious. So, I’ll try to write a detailed blog about it.
1. Project Structure
It’s just a simple project structure.
1
2
3
4
5
6
7
8
9
10
.
├── My_Project
│ ├── __init__.py
│ ├── dataclass.py
│ ├── main.py
│ └── util.py
├── README.md
├── pyproject.toml
├── sample
└── setup.py
In my own opinion, split main code and utility code is good to maintain the code. And also, from python@3.7, we can use dataclass (like struct in C). So, I recommend to use it for readability and accessibility.
1.1. Project Code Structure
1
2
# My_Project/__init__.py
from .main import MyClass
for python packaging, we need to have __init__.py file in the directory.
1
2
3
4
5
6
7
8
9
10
# My_Project/dataclass.py
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class MyData:
name: str
age: int
address: Optional[str] = None
friends: List[str] = None
You can cusomize the dataclass as you want.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# My_Project/main.py
from .util import MyUtil
class MyClass:
def __init__(self):
self.util = MyUtil()
def print(self):
print("MyClass")
self.util.print()
if __name__ == "__main__":
my_class = MyClass()
my_class.print()
I usually use main.py to write main Class and test it.
1
2
3
4
5
6
7
8
9
10
# My_Project/util.py
def print():
print("test1234")
class MyUtil:
def __init__(self):
pass
def print(self):
print("MyUtil")
I just use util.py to write my custom classes and functions.
But, you can split it as you want functionally as you want.
1.2. pyproject.toml and setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[project]
name = "My-Project"
version = "0.0.1"
description = "My Simple Testing Project"
readme = {file = "README.md", content-type = "text/markdown"}
dependencies = ["requests", "tqdm"]
maintainers = [{name = "h1ghl1kh7", email = "h1ghl1kh7@gmail.com"}]
license = {text = "MIT License"}
[tool.setuptools]
packages = ["My_Project"] # project folder name
[project.urls]
Repository = "https://github.com/h1ghl1kh7/My_Project"
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
It is a simple pyproject.toml file, and when I uploaded my own project, I used this format.
It you want to know more about pyproject.toml, you can refer to Python Packaging User Guide.
The content of setup.py is very simple.
It’s because I use pyproject.toml to manage the project (You don’t write anything in setup.py if you write pyproject.toml).
1
2
3
4
5
# setup.py
from setuptools import setup
if __name__ == "__main__":
setup()
2. Upload to Pypi
Register to pypi.org Get api from (Account Settings -> API Tokens)
When you upload the project, it asks you to input token every time.
So, I recommend to write token into ~/.pypirc file.
1
2
3
[pypi]
username = __token__
password = pypi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
If then, it automatically pass the token check process with this information.
1
2
python3 setup.py sdist bdist_wheel
python3 -m twine upload dist/*
Execute the above commands, package is built and uploaded.
It automatically create new project on pypi, so, you don’t have to create project on site.
And, I recommend to remove dist, build, My_Project.egg-info directories and rebuild the project when you upload another version of the project.