Python Packaging Guide
Tags: python, packaging, pypi, tutorial
Published: 2020-06-07 18:59:13

<i>Long post Alert</i>

Wow, this feels nice. I am finally posting my first DEV Post and it definitely feels satisfying.

Now now, enough about me. Diving straight into the topic.

What's so special about Open Source? Capabilities? NO. Usage? NO. (Maybe but not the point). The answer is <b>Contribution</b>. What makes Open source so great is that, anybody can contribute to the Open Source community. When one developer can create magic, imagine what can happen when all of the best come together to create magic.
So this post is going to be an extensive guide to package a Python code and to distribute it to PyPi - The official <b>Py</b>thon <b>P</b>ackage <b>i</b>ndex. When I first started to learn to code in Python, I found the urge to contribute to the Open Source community.. The feeling of wanting to give back it back to the community. All done and said, the feeling was a great point to start - but was that enough? Definitely no. I had a great difficulty in finding the right guide that taught me how to package, from the very basics. No offense to the other guides that proved super helpful, but I had to aggregate knowledge from various sources and I finally learnt how to do it. That's what drove me to write this post - So that, nobody has to ever search through multiple guides and feel disheartened/lost.

Now, starting with the <b>A</b> until the <b>Z</b> of the packaging process.
<b> What is a package?</b> - A package is mainly the Python code file. The ".py" file. It's called a package because we create a folder and place the .py file inside it and thus the folder is called a Package.
Super simple, right? . Yes, the rest is going to be easy to follow through as well.

<b> What is PyPi?</b> - The full form of PyPi is Python Packaging index. When we install a package/library using pip install command, PyPi is the repository that supplies the package. In short, it's a massive library that houses all the packages contributed by amazing developers like all of you and when someone installs using pip install command, it straight away downloads the files uploaded by you (the zipped file) and install it for you, so you can simply call it by "import packagename" in your code and utilise it.

<b> Is the code file the only file that's needed? </b> - No. The code file is obviously the most important file, but there are other supporting files that are required and I'm going to outline them following this.

Now, every package requires the below files at the minimum:

<ol>
<li>The .py python code file</li>
<li>The setup.py code file</li>
<li>The &#95;&#95;init__.py code file</li>
<li>The setup.cfg file</li>
<li>The README.MD file</li>
</ol>
Optional: (But very good to follow a disciplined way of uploading)
<ul>
<li>The License File</li>
</ul>

Now, let's learn how to package a python file, together. Start with opening your favorite editor: Either VSCode or Sublime Text or Atom. Mine's VSCode :).

<b><h3>The folder and the .py file</h3></b>

First, the most important thing is to create a folder that's named exactly how you want to name your package. Let's say, you want to package a hello-world code; 
<ul>
<li>Start with creating a folder called "Helloworld".<b>NOTE: Before you name your package, search for it on https:pypi.org and ensure it's not already available & pick a unique name</b></li> 
<li>Then, enter the folder and create the .py file as Helloworld.py</li>
</ul>
This is how the code file should look like; (Note: The files should have a class and a method)

```
class Helloworld(): #This needs to be the same as your package name
    def __init__(self): #this is the constructor for the class.
        return None
    def sayHello(self): #this is the method that you would call
        return "Hello World"
```
<ul>
Points to note in the Python code:
<li>Make sure the code has no print statements except what you want to "return" to the user (See what I did there? Use the return statement to print the final output to the user)</li>
<li>You have to have a class, and a method inside to call</li>
<li>Use comments or docstrings if needed</li>
</ul>


<b><h3>The setup.py file</h3></b>

Now, the code file (the most important part is over).
The next file is, the setup.py file and here is the code for that (based on the Hello World example)


```
import io
import os
import sys
import setuptools
from setuptools import find_packages, setup, Command

with open("README.md", "r") as fh:
    long_description = fh.read()

setup(
  name = 'Helloworld', 
  packages = ['Helloworld'], 
  version = '1.0',
  license='MIT',
  description = "Python library that says Hello World when called.", 
  long_description=long_description,
  long_description_content_type="text/markdown",
  author = 'XXX',
  author_email = 'xxx@gmail.com',
  url = 'https://github.com/xxx/Helloworld', 
  py_modules=['mypackage'],
  entry_points={'console_scripts': ['mycli=mymodule:cli'],},
  keywords = ['Simple'],
  classifiers=[
    'Development Status :: 4 - Beta',
    'Intended Audience :: Developers',
    'Topic :: Software Development :: Build Tools',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 3.4',  
    'Programming Language :: Python :: 3.5',
    'Programming Language :: Python :: 3.6'
  ],
  python_requires='>=3.1',
)
```



<br>Explanation:
<ul>
<li>name specifies the code file/folder name</li>
<li>package specifies the same as above within square braces</li>
<li>version specifies the version you want to start with; good to start with v1.0</li>
<li>description is a description of your library and what it does</li>
<li>long description specifies it to open long description (the readme typically)</li>
<li>long description content type specifies it to use README.md file</li>
<li>Author - Yup, that's you! Look at yourself - You're an author now ;)</li>
<li>Author email - Give in your email so people can reach out to you for any doubts</li>
<li>url - will get to this later but xxx = your github user name followed by your package name</li>
<li>pymodules - leave it as mypackage</li>
<li>entry points - leave it as it is</li>
<li>keywords - Specify in a couple of words that describe your package</li>
<li>classifiers - Good to start Development status as 3-Alpha or 4-Beta and then scale it as your library grows</li>
<li>You can leave the rest as it is unless your programming language version is different and license is different</li>
<li>python_requires - Finally, you specify here the version it's built on and the version it will run on(The same) use >=3.x</li></ul>

<b><h3>The `__init__.py` file</h3></b>

Now, on to the next file - The `__init__.py` file

Just import your class name in this file & that's all.

```
from Helloworld.Helloworld import Helloworld
```

<code>This means that, from foldername.filename import classname</code><br>

<b><h3>The setup.cfg file</h3></b>

Next, it's the setup.cfg file. Create a blank file inside the same folder and save it as setup.cfg (where cfg indicates configuration). Here's what the setup.cfg will contain:

```
[metadata]
description-file = README.md
```

Done!

Now, we're almost there. Next is the README.MD file.


<b><h3>The README.MD file</h3></b>

Here, you can choose to create and edit it yourself or do it via websites that help you.

If you choose to create it yourself, create a blank file in your editor and name it README.MD (md refers to markdown format)

You can just input:
```
#Helloworld
Python library that says Hello World when called
```

It can be as simple as it is. But I'd suggest that you include HTML Tags and add installation options, syntax and an example code of how to use. Well, anybody'd know how to use Helloworld :) But I'm pretty sure your packages are going to be a bit more complex than just a Helloworld.

To use it from a Website, you can refer to https://www.makeareadme.com/ which has predefined templates and etc.

<b><h3>The LICENSE.txt file</h3></b>


Finally, the optional LICENSE.txt file which is just a simple text file. You can use various open source licenses like MIT's, GNU's etc. I personally prefer going with MIT's. But you can choose it based on your need at - https://choosealicense.com/.

Getting to the github URL, open a github repository with exactly the same name as the package name and upload all the files into it; Copy all the files into it and mention the repository URL in the setup.py url field. You're now done with all the files.

Now, you have all the 6 files namely:

setup.py
README.MD
Helloworld (Folder)
||-- `Helloworld.py` (inside the folder)
||-- `setup.cfg` (inside the folder)
||-- `LICENSE.txt` (inside the folder)
||-- `__init__.py` (inside the folder)

<b> NOTE:
<ul>
<li>Helloworld.py, setup.cfg, LICENSE.txt & __init__.py needs to be inside the Helloworld folder.</li>
<li>setup.py and README.MD needs to be outside the folder (the main parent folder).</li>
</ul>

<b><h3>The PyPi Account setup</h3></b>

Quick note, before we upload the package, you need to have a pypi account.
<ul>
<li>Go to https://pypi.org</li>
<li>Create an account</li>
<li>Remember your account username and password once you have created because we will need them to upload the package</li>
<li>Also install twine (a python utility) that will help us upload our package</li>
<li> Install twine using <code>pip install twine</code></li>
</ul>

<h4> TIME TO UPLOAD YOUR PACKAGE!!!! </h4>

<b><h3>The Upload Process </h3></b>

<ol>
<li>First, open your command prompt and navigate to the main folder that has setup.py, README file and the package folder using cd folderpath</li>
<li>Type in <code>setup.py sdist</code></li>
<li>You will receive a message saying the distribution has been created and everything under package name has been deleted !! (DON'T WORRY; You're in the right direction</li>
<li>Now your distribution would have been created in the parent folder under a folder named "dist" as "Helloworld-1.0.tar.gz"</li>
<li>Get back to the command prompt and type in <br><code>twine upload dist/Helloworld-1.0.tar.gz</code> and hit enter</li>
<li>You will be asked for your pypi username and password</li>
<li>Enter them AAAAAAAAAAAAND YOU'RE DONE</li>
<h4>YOUR PACKAGE IS NOW OFFICIALLY AVAILABLE ON THE INTERNET</h4>
</ol>

Clap for yourself :) You deserve it!

To check if your package works, open a blank python file, and type <br><code>import Helloworld</code> and run the file.
No errors? You have done it! Congrats!

Thank you for listening through! Now go ahead and contribute to the open source society!!!!

Let me know your feedback :)