<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ package - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ package - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 21 May 2026 10:21:21 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/package/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Manage Python Packages with uv ]]>
                </title>
                <description>
                    <![CDATA[ Python package managers let you install and manage dependencies—like NumPy, pandas, and so on—right from your terminal. In this article, you will learn how to use uv—an extremely fast Python package manager. Prerequisites To get the most out of this ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-manage-python-packages-with-uv/</link>
                <guid isPermaLink="false">69089c3b30ea29f0efb3f4fd</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ package ]]>
                    </category>
                
                    <category>
                        <![CDATA[ terminal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hew Hahn ]]>
                </dc:creator>
                <pubDate>Mon, 03 Nov 2025 12:12:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762169941014/9e66858d-3ba4-434e-a9f1-84d42a316192.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Python package managers let you install and manage dependencies—like NumPy, pandas, and so on—right from your terminal.</p>
<p>In this article, you will learn how to use <code>uv</code>—an extremely fast Python package manager.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this tutorial, you will need to:</p>
<ul>
<li><p>Know how to execute commands in your terminal,</p>
</li>
<li><p>Be familiar with basic Python development/scripting.</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-should-you-use-uv">Why Should You Use uv?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-uv">How to Install uv</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-a-project-with-uv">How to Set up a Project with uv</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-commonly-used-uv-commands">Commonly Used uv Commands</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-add-a-dependency">How to Add a Dependency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-remove-a-dependency">How to Remove a Dependency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-run-python-code">How to Run Python Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-move-your-project">How to Move Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-and-run-tools">How to Add and Run Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-run-tools-without-adding-them-to-your-project">How to Run Tools Without Adding Them to Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-multiple-python-versions">How to Manage Multiple Python Versions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-migrate-from-pip-to-uv">How to Migrate from pip to uv</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-why-should-you-use-uv">Why Should You Use uv?</h2>
<p><code>uv</code> is a free and open-source Python project management tool. Written in Rust, <code>uv</code> is fast and easy-to-use. It has become a standard package manager for modern Python development. You can also use it to manage your virtual environments, making it a good alternative for <code>pip</code> and <code>venv</code>.</p>
<p><a target="_blank" href="https://docs.astral.sh/uv/">Speed tests</a> have shown that <code>uv</code> is faster than other popular package managers when it comes to installing dependencies.</p>
<h2 id="heading-how-to-install-uv">How to Install uv</h2>
<p>To install <code>uv</code>, simply execute the following command in your terminal:</p>
<p>For Linux/macOS:</p>
<pre><code class="lang-bash">curl -LsSf https://astral.sh/uv/install.sh | sh
</code></pre>
<p>For Windows:</p>
<pre><code class="lang-powershell">powershell <span class="hljs-literal">-ExecutionPolicy</span> ByPass <span class="hljs-literal">-c</span> <span class="hljs-string">"irm https://astral.sh/uv/install.ps1 | iex"</span>
</code></pre>
<h2 id="heading-how-to-set-up-a-project-with-uv">How to Set up a Project with uv</h2>
<p>To start a new project with <code>uv</code>, run the following command:</p>
<pre><code class="lang-bash">uv init freecodecamp-project
</code></pre>
<p>This creates the folder <code>/freecodecamp-project</code> in your working directory with the following structure:</p>
<pre><code class="lang-bash">├── .gitignore <span class="hljs-comment"># hidden text file that lists files to be ignored by git</span>
├── .python-version <span class="hljs-comment"># hidden text file that keeps record of your Python's version number</span>
├── README.md
├── main.py
└── pyproject.toml
</code></pre>
<p><code>README.md</code> is a markdown file, which you can use to communicate information about your project (just as a repository README file on GitHub). <code>pyproject.toml</code> is the configuration file for your project. You can edit it to change your project’s name, version and description. It also keeps track of dependencies you add to project. Last but not least, <code>main.py</code> is where you put your Python code.</p>
<h2 id="heading-commonly-used-uv-commands">Commonly Used uv Commands</h2>
<p>Before you can run any <code>uv</code> commands, move your terminal into your project folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> freecodecamp-project
</code></pre>
<h3 id="heading-how-to-add-a-dependency">How to Add a Dependency</h3>
<p>To add a dependency (for example, NumPy), run:</p>
<pre><code class="lang-bash">uv add numpy
<span class="hljs-comment"># or if you need a specific version</span>
uv add <span class="hljs-string">'numpy==2.3.0'</span>
</code></pre>
<p>This automatically adds a virtual environment and a <code>.lock</code> file with a new entry:</p>
<pre><code class="lang-bash">├── .venv <span class="hljs-comment"># hidden folder inside of which your required packages will be installed</span>
└── uv.lock
</code></pre>
<p>The <code>.lock</code> file keeps record of the exact versions of your dependencies and their required packages. You should never modify it directly.</p>
<h3 id="heading-how-to-remove-a-dependency">How to Remove a Dependency</h3>
<p>To remove a dependency, run:</p>
<pre><code class="lang-bash">uv remove numpy
</code></pre>
<p>This will also remove the corresponding entry from the <code>.lock</code> file.</p>
<h3 id="heading-how-to-run-python-code">How to Run Python Code</h3>
<p>To run your Python script, execute:</p>
<pre><code class="lang-bash">uv run main.py
</code></pre>
<p>This will run the code inside the created virtual environment with the installed dependencies in one step! That is, you don’t need to explicitly activate the virtual environment and then run your code.</p>
<h3 id="heading-how-to-move-your-project">How to Move Your Project</h3>
<p>Sometimes you may want to move your project to another machine. Maybe you want to share it with colleagues, or set it up on a production server. Getting to run your code on another machine has never been easier than with <code>uv</code>. You can simply copy your project folder to the destination environment and run the following command in the destination terminal:</p>
<pre><code class="lang-bash">uv sync --locked
</code></pre>
<p>This installs the exact versions of your project dependencies!</p>
<h3 id="heading-how-to-add-and-run-tools">How to Add and Run Tools</h3>
<p>Sometimes you may need tools like <code>ruff</code>, a Python linter (code formatter), which you can add just like any other dependency to your project:</p>
<pre><code class="lang-bash">uv add ruff
</code></pre>
<p>To run an installed tool, execute:</p>
<pre><code class="lang-bash">uv run ruff check
</code></pre>
<h3 id="heading-how-to-run-tools-without-adding-them-to-your-project">How to Run Tools Without Adding Them to Your Project</h3>
<p>Sometimes you may not want to add tools to your dependencies. For example, because you just want to make one-off checks. <code>uv</code> has got you covered with <code>tool run</code>. Simply run:</p>
<pre><code class="lang-bash">uv tool run ruff check
<span class="hljs-comment"># or equivalently </span>
uvx ruff check
</code></pre>
<p>This will run the tool in an isolated environment independent.</p>
<h3 id="heading-how-to-manage-multiple-python-versions">How to Manage Multiple Python Versions</h3>
<p>If your system has Python installed, <code>uv</code> will use it. Otherwise, it will automatically install the latest Python version when you execute Python code or create a virtual environment with <code>uv</code>. However, you can also use it to manage multiple Python versions:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># install the latest Python version</span>
uv python install
<span class="hljs-comment"># install multiple Python versions</span>
uv python install 3.11 3.12
<span class="hljs-comment"># list all installed Python versions</span>
uv python list
<span class="hljs-comment"># set the version to be used in the current project (.python-version)</span>
uv python pin 3.11
</code></pre>
<h3 id="heading-how-to-migrate-from-pip-to-uv">How to Migrate from pip to uv</h3>
<p><code>uv</code> works as drop-in replacement for <code>pip</code>, meaning that you can use common <code>pip</code> commands with <code>uv</code>. Let’s say you received a <code>requirements.txt</code> file. To install the listed dependencies, you can run:</p>
<pre><code class="lang-bash">uv pip install -r requirements.txt
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You just learned how to use <code>uv</code>! Before <code>uv</code>, managing dependencies, virtual environments and Python versions had been notoriously cumbersome. As an ML engineer at <a target="_blank" href="https://mljobs.io">MLjobs.io</a>, I can safely say that <code>uv</code> has been a game changer. Check out <code>uv</code>'s <a target="_blank" href="https://docs.astral.sh/uv/">documentation</a> to learn more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is deb-get? How to Install the Debian Package with the deb-get Command ]]>
                </title>
                <description>
                    <![CDATA[ deb-get is a new command line utility built by Martin Wimpress, an active contributor to the Linux community.  You can use this utility to install third-party packages on your Debian machine. It only works with Debian or Debian-based distros like Ubu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-deb-get-debian-package-manager/</link>
                <guid isPermaLink="false">66d038c0c1024fe75b758f5e</guid>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ package ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rajdeep Singh ]]>
                </dc:creator>
                <pubDate>Wed, 07 Sep 2022 18:27:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Debian-deb-get.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><code>deb-get</code> is a new command line utility built by <a target="_blank" href="https://twitter.com/m_wimpress">Martin Wimpress</a>, an active contributor to the Linux community. </p>
<p>You can use this utility to install third-party packages on your Debian machine. It only works with Debian or Debian-based distros like Ubuntu, Linux mint, Kali Linux, and so on. </p>
<h2 id="heading-why-should-you-use-deb-get">Why Should You Use <code>deb-get</code>?</h2>
<p>This is a great question. I think <code>deb-get</code> is more secure and faster than other package managers. </p>
<p>For example, the snap package is way slower, and flatpack takes a lot of space to install a single package in your Debian system. </p>
<p>The <code>deb-get</code> manager only uses <code>.deb</code> files from an official source and installs them in your system.</p>
<h3 id="heading-advantages-of-the-deb-get-command">Advantages of the <code>deb-get</code> Command</h3>
<p>I think the <code>deb-get</code> command has more advantages than other package managers like snap, Flatpak, and so on. </p>
<ol>
<li>The <code>deb-get</code> command is a lightweight and stable bash command utility.</li>
<li>You can easily contribute with the deb-get CLI tool. You can add your own package or other packages in deb-get. To add a package, you need three to four lines of code.</li>
<li>The <code>deb-get</code> command installs official packages from source. It does not support third-party build packages.</li>
</ol>
<h3 id="heading-disadvantages-of-the-deb-get-command">Disadvantages of the <code>deb-get</code> Command</h3>
<p>Again, the <code>deb-get</code> command has more advantages than disadvantages. But the main disadvantage is that <code>deb-get</code> is a new utility. For that reason, it supports fewer packages than snap or flatpack.</p>
<h2 id="heading-how-to-install-the-deb-get-command-on-a-debian-distro">How to Install the <code>deb-get</code> Command on a Debian Distro</h2>
<p>You can install <code>deb-get</code> with a bash script. For installation, you need the <code>curl</code> command to install <code>deb-get</code> in your Debian distro. If you've already installed the <code>curl</code> command on your distro, then skip this step.</p>
<pre><code>sudo apt install curl  <span class="hljs-comment">// alredy install,then skip it.</span>
curl -sL https:<span class="hljs-comment">//raw.githubusercontent.com/wimpysworld/deb-get/main/deb-get | sudo -E bash -s install deb-get</span>
</code></pre><p>The command output looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Install-deb-get-command-by-linux.png" alt="Install deb-get command in debian distro" width="600" height="400" loading="lazy">
<em>Your deb-get installation looks like this.</em></p>
<p>Confirm that <code>deb-get</code> has been installed on your machine, then run the <code>deb-get version</code> command on your terminal.</p>
<pre><code>&gt; deb-get version
<span class="hljs-number">0.3</span><span class="hljs-number">.5</span>
</code></pre><h2 id="heading-how-to-use-deb-get">How to Use <code>deb-get</code></h2>
<h3 id="heading-how-to-install-the-debian-package-with-deb-get">How to Install the Debian Package with <code>deb-get</code></h3>
<p>With the <code>deb-get install</code> command, you can install packages from <code>deb-get</code>.</p>
<pre><code>❯ deb-get install    &lt;package-name&gt;
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/install-package-from-deb-get.png" alt="Install github-cli with deb-get command" width="600" height="400" loading="lazy">
<em>Install github-cli with the deb-get command</em></p>
<h3 id="heading-how-to-delete-a-package-with-deb-get">How to Delete a Package with <code>deb-get</code></h3>
<p>With the <code>deb-get purge</code> or <code>deb-get remove</code> command, you can delete any package with <code>deb-get</code>. I prefer the <code>deb-get purge</code> command, but both flags (<code>purge</code> and <code>remove</code>) work the same. <code>purge</code> flags delete all config files which install or config with the package.</p>
<pre><code>❯ deb-get purge   &lt;package-name&gt;
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Delete-github-cli.png" alt="Delete or uninstall the package with the deb-get command" width="600" height="400" loading="lazy">
<em>Delete or uninstall the package with the deb-get command</em></p>
<h3 id="heading-how-to-check-which-packages-are-available-in-deb-get">How to Check Which Packages Are Available in <code>deb-get</code></h3>
<p>You check package availability in two ways. First, you can visit the <a target="_blank" href="https://github.com/wimpysworld/deb-get#supported-software">deb-get official docs</a> to find a list of available packages. </p>
<p>The second way is a command line utility. deb-get provides a lot of flags or options. My favorite is the two flags that come with deb-get.</p>
<ol>
<li><code>deb-get list</code></li>
<li><code>deb-get search  &lt;package-name&gt;</code> </li>
</ol>
<h3 id="heading-how-to-use-deb-get-list">How to use deb-get list</h3>
<p>The <code>deb-get list</code> flag provides a list of all the available packages in the terminal. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/deb-get-list.png" alt="list of available package in deb-get command" width="600" height="400" loading="lazy">
<em>list of available package</em></p>
<h3 id="heading-how-to-use-deb-get-search">How to use deb-get search  </h3>
<p>The <code>deb-get search  &lt;package-name&gt;</code> flag helps you find a package by its name. If the flag finds a package, then it returns the package. Otherwise, it returns an empty string.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/deb-get-search-chrome.png" alt="Search package with deb-get" width="600" height="400" loading="lazy">
<em>Search package with deb-get</em></p>
<p>You can check all the available commands with <code>deb-get help</code>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I think the deb-get distributor or Debian package manager has more potential than the other package managers.</p>
<p>Every package manager has advantages and disadvantages. But I believe deb-get is a game-changer in the future. </p>
<p>You can share and follow on <a target="_blank" href="https://twitter.com/Official_R_deep">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/officalrajdeepsingh/">Linkedin</a>. If you like my work, feel free to read more content on <a target="_blank" href="https://officialrajdeepsingh.dev/">officialrajdeepsingh.dev</a> and <a target="_blank" href="https://officialrajdeepsingh.medium.com/">Medium</a>.</p>
<h3 id="heading-references">References</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/wimpysworld/deb-get">https://github.com/wimpysworld/deb-get</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/wimpysworld/deb-get/blob/main/CONTRIBUTING.md">https://github.com/wimpysworld/deb-get/blob/main/CONTRIBUTING.md</a></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create and Upload Your First Python Package to PyPI ]]>
                </title>
                <description>
                    <![CDATA[ A few weeks ago, I wanted to learn how to build my first Python package, and I was trying to figure out where to start.  Well, I got confused and a bit stressed trying to find a simple and easy tutorial I could use to get started. For this ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-and-upload-your-first-python-package-to-pypi/</link>
                <guid isPermaLink="false">66c375e463ac6ce6ab8eba89</guid>
                
                    <category>
                        <![CDATA[ package ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rochdi Khalid ]]>
                </dc:creator>
                <pubDate>Mon, 11 Apr 2022 15:40:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/cover-image-python-packaging-blog-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A few weeks ago, I wanted to learn how to build my first Python package, and I was trying to figure out where to start. </p>
<p>Well, I got confused and a bit stressed trying to find a simple and easy tutorial I could use to get started. For this reason, I decided to write this tutorial documenting how I built my first Python package.</p>
<h2 id="heading-what-is-a-package-in-python">What is a package in Python?</h2>
<p>Before we get started, we should know a package means in Python.</p>
<p>A Python package is a directory that contains a bunch of modules with a dependency file called <code>__init__.py</code>. This file can be completely empty and you use it to mark the directory on a disk as a Python package. </p>
<p>The following shows an example of a package directory:</p>
<pre><code>package
    __init__.py
    module_a.py
    module_b.py
    module_c.py
</code></pre><p>The <code>__init__.py</code> is a dependency file that helps Python look for the available modules in our package directory. If we remove this file, Python will fail to import our modules.</p>
<h2 id="heading-packages-vs-modules-in-python">Packages vs modules in Python</h2>
<p>You should now understand that Python packages create a structured directory with several modules, but what about modules? Let's make sure we understand the difference between a package and a module:</p>
<p>A <strong>Module</strong> always corresponds to a single Python file <em>turtle.py</em>. It contains logic like classes, functions, and constants.</p>
<p>A <strong>Package</strong> is basically a module that could contain many modules or sub-packages.</p>
<h2 id="heading-package-structure">Package structure</h2>
<p>Packages don't only contain modules, though. They consist of top-level scripts, documentation, and tests, as well. The following example shows how a basic Python package can be structured:</p>
<pre><code>package_name/
    docs/
    scripts/
    src/
        package_a
            __init__.py
            module_a.py
        package_b
            __init__.py
            module_b.py
    tests/
        __init__.py
        test_module_a.py
        test_module_b.py
    LICENSE.txt
    CHANGES.txt
    MANIFEST.in
    README.txt
    pyproject.toml
    setup.py
    setup.cfg
</code></pre><p>Let's understand what each file in the tree above is used for:</p>
<ul>
<li><strong>package_name</strong>: represents the main package.</li>
<li><strong>docs</strong>: includes documentation files on how to use the package.</li>
<li><strong>scripts/</strong>: your top-level scripts.</li>
<li><strong>src</strong>: where your code goes. It contains packages, modules, sub-packages, and so on.</li>
<li><strong>tests</strong>: where you can put unit tests.</li>
<li><strong>LICENSE.txt</strong>: contains the text of the license (for example, MIT).</li>
<li><strong>CHANGES.txt</strong>: reports the changes of each release.</li>
<li><strong>MANIFEST.in</strong>: where you put instructions on what extra files you want to include (non-code files).</li>
<li><strong>README.txt</strong>: contains the package description (markdown format).</li>
<li><strong>pyproject.toml</strong>: to register your build tools.</li>
<li><strong>setup.py</strong>: contains the build script for your build tools.</li>
<li><strong>setup.cfg</strong>: the configuration file of your build tools.</li>
</ul>
<p>Note that there are two options for how to include our test files in our main package. We can keep it at the top level as we did above or put it inside the package like the following:</p>
<pre><code>package_name/
      __init__.py
      module_a.py
      module_b.py
      test/
          __init__.py
          test_module_a.py
          test_module_b.py
</code></pre><p>In my opinion, I think keeping tests at the top level can help a lot especially when our tests require reading and writing other external files.</p>
<h2 id="heading-should-you-use-setupcfg-or-setuppy">Should you use setup.cfg or setup.py?</h2>
<p>The <strong>setup.py</strong> and <strong>setup.cfg</strong> are the default packaging tools within PyPI, setuptools, pip, and the standard python library. </p>
<p>Here, they represent the configuration and build scripts for setuptools. They both tell the setuptools how the package can be built and installed. </p>
<p>The mentioned file contains information like the version, packages, and files to include, along with any requirements.</p>
<p>The following shows an example of <code>setup.py</code> that uses some <code>setup()</code> arguments. You can find more arguments <a target="_blank" href="https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args">here</a>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> setuptools

<span class="hljs-keyword">with</span> open(<span class="hljs-string">"README.md"</span>, <span class="hljs-string">"r"</span>, encoding = <span class="hljs-string">"utf-8"</span>) <span class="hljs-keyword">as</span> fh:
    long_description = fh.read()

setuptools.setup(
    name = <span class="hljs-string">"package-name"</span>,
    version = <span class="hljs-string">"0.0.1"</span>,
    author = <span class="hljs-string">"author"</span>,
    author_email = <span class="hljs-string">"author@example.com"</span>,
    description = <span class="hljs-string">"short package description"</span>,
    long_description = long_description,
    long_description_content_type = <span class="hljs-string">"text/markdown"</span>,
    url = <span class="hljs-string">"package URL"</span>,
    project_urls = {
        <span class="hljs-string">"Bug Tracker"</span>: <span class="hljs-string">"package issues URL"</span>,
    },
    classifiers = [
        <span class="hljs-string">"Programming Language :: Python :: 3"</span>,
        <span class="hljs-string">"License :: OSI Approved :: MIT License"</span>,
        <span class="hljs-string">"Operating System :: OS Independent"</span>,
    ],
    package_dir = {<span class="hljs-string">""</span>: <span class="hljs-string">"src"</span>},
    packages = setuptools.find_packages(where=<span class="hljs-string">"src"</span>),
    python_requires = <span class="hljs-string">"&gt;=3.6"</span>
)
</code></pre>
<p>The <code>setup.cfg</code> is written in a different format compared to <code>setup.py</code>, and contains basically two essential keys, <code>command</code> and <code>options</code>. </p>
<p>The <code>command</code> key represents one of the <strong>distutils</strong> commands, while the <code>options</code> key defines the options the command can support.</p>
<pre><code>[command]
option = value
</code></pre><p>The following shows an example of <code>setup.cfg</code> that uses some metadata and options. You can find a variety of metadata and options <a target="_blank" href="https://setuptools.pypa.io/en/latest/userguide/declarative_config.html">here</a>:</p>
<pre><code>[metadata]
name = package-name
version = <span class="hljs-number">0.0</span><span class="hljs-number">.1</span>
author = name <span class="hljs-keyword">of</span> the author
author_email = author@example.com
description = short package description
long_description = file: README.md
long_description_content_type = text/markdown
url = package url
project_urls =
    Bug Tracker = package issues url
classifiers =
    Programming Language :: Python :: <span class="hljs-number">3</span>
    <span class="hljs-attr">License</span> :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
package_dir =
    = src
packages = find:
python_requires = &gt;=<span class="hljs-number">3.6</span>

[options.packages.find]
where = src
</code></pre><p>The <code>setup.py</code> and <code>setup.cfg</code> are both specific to setuptools. Also, the <code>setup.cfg</code> can safely be moved to <code>pyproject.toml</code>. </p>
<p>Here, the idea is that maybe one day we'll want to switch to other build systems like <strong>flit</strong> or <strong>poetry</strong>. In that case, all we'll need to do is change the build-system entry (setuptools for example) in <code>pyproject.toml</code> to something like flit or poetry rather than starting over from scratch. </p>
<p><a target="_blank" href="https://packaging.python.org/en/latest/key_projects/#build">Here</a> you can find information about other tools that build and distribute Python packages.</p>
<p>No matter which configuration file we chose, we are "locked-in" to maintaining that particular configuration file, either pyproject.toml, setup.cfg, or setup.py.</p>
<p>According to the <a target="_blank" href="https://packaging.python.org/en/latest/">Python Packaging User Guide</a>, <code>setup.cfg</code> is preferred because it's static, clean, easier to read, and avoids encoding errors.</p>
<h2 id="heading-how-to-build-your-first-python-package">How to build your first Python package</h2>
<p>Now, it's time to start building a simple Python package. We will use setuptools as a build system and we will configure our project using <code>setup.cfg</code> and <code>pyproject.toml</code>.</p>
<h3 id="heading-set-up-the-package-files">Set up the package files</h3>
<p>For this simple package, we need to structure our directory by adding the dependency files needed to get the package ready for distribution. This is how to structure our package:</p>
<pre><code>basicpkg/
    src/
        divide
            __init__.py
            divide_by_three.py
        multiply
            __init__.py
            multiply_by_three.py
    tests/
        __init__.py
        test_divide_by_three.py
        test_multiply_by_three.py
    LICENSE.txt
    README.txt
    pyproject.toml
    setup.cfg
</code></pre><p>Our main package consists of two packages: the first one to divide numbers by three, and the other to multiply numbers by three. </p>
<p>Also, we ignore some files like <code>CONTEXT.txt</code>, <code>MANIFEST.in</code>, and the <code>docs/</code> directory to keep things simple at the moment. But we need the <code>test/</code> directory to include our unit tests to test the package's behaviors.</p>
<h3 id="heading-add-some-logic-to-our-modules">Add some logic to our modules</h3>
<p>As always, we will keep the <code>__init__.py</code> empty. Then, we need to put some logic in our modules to perform our operations. </p>
<p>For the divide package, let's add the following content into <code>divide_by_three.py</code> to divide any number by three:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">divide_by_three</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-keyword">return</span> num / <span class="hljs-number">3</span>
</code></pre>
<p>The same logic applies to <code>multiply_by_three.py</code> inside the multiply package. But, this time is to multiply any number by three:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_by_three</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-keyword">return</span> num * <span class="hljs-number">3</span>
</code></pre>
<p>Feel free to add more packages and modules to perform other kinds of operations. For example, you can add packages to do addition and subtraction tasks.</p>
<h3 id="heading-test-our-modules">Test our modules</h3>
<p>It's good to practice adding automated tests to any program we create. We will use <code>unittest</code> to test our modules and the package's behavior. </p>
<p>Inside the <code>test/</code> directory, let's add the following code to <code>test_divide_by_three.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">from</span> divide.by_three <span class="hljs-keyword">import</span> divide_by_three 

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestDivideByThree</span>(<span class="hljs-params">unittest.TestCase</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_divide_by_three</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(divide_by_three(<span class="hljs-number">12</span>), <span class="hljs-number">4</span>)

unittest.main()
</code></pre>
<p>We imported TestCase from <code>unittest</code> to perform our automated testing. Then, we imported our division method <code>divide_by_three()</code> from <code>by_three</code> module that is located inside the divide package. </p>
<p>If we remove the <code>__init__.py</code> here, Python will no longer be able to find our modules. </p>
<p>The <code>.assertEqual()</code> is used to check the equality of the two values above (divide_by_three(12) and 4). The <code>unittest.main()</code> is instantiated to run all our tests.</p>
<p>The same logic applies to <code>test_multiply_by_three.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest
<span class="hljs-keyword">from</span> multiply.by_three <span class="hljs-keyword">import</span> multiply_by_three

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestMultiplyByThree</span>(<span class="hljs-params">unittest.TestCase</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_multiply_by_three</span>(<span class="hljs-params">self</span>):</span>
        self.assertEqual(multiply_by_three(<span class="hljs-number">3</span>), <span class="hljs-number">9</span>)

unittest.main()
</code></pre>
<p>To run the tests, type the following in your terminal/command:</p>
<p>For Linux:</p>
<pre><code>python3 tests/test_divide_by_three.py
</code></pre><p>For Windows:</p>
<pre><code>py tests/test_divide_by_three.py
</code></pre><p>Do the same to test the multiply module. If our tests run successfully, you should get the following:</p>
<pre><code>.
----------------------------------------------------------------------
Ran <span class="hljs-number">1</span> test <span class="hljs-keyword">in</span> <span class="hljs-number">0.000</span>s

OK
</code></pre><p>If you add extra packages and modules, try to add some <code>unittest</code> methods to them. This is going to be a good challenge for you.</p>
<h3 id="heading-configure-metadata-using-setupcfg">Configure metadata using setup.cfg</h3>
<p>Next, we need to add a configuration file for setuptools. As mentioned before, this config file will tell setuptools how our package can be built and installed. </p>
<p>So, we need to add the following metadata and options to our <code>setup.cfg</code>. Then, don't forget to choose a different name because I already uploaded this package with the name below to <a target="_blank" href="https://test.pypi.org/project/basicpkg/">TestPyPi</a>. Also, change other information like author, email, and project URLs to distribute the package with your info.</p>
<pre><code>[metadata]
name = basicpkg
version = <span class="hljs-number">1.0</span><span class="hljs-number">.0</span>
author = your name
author_email = your email
description = A simple Python package
long_description = file: README.md, LICENSE.txt
long_description_content_type = text/markdown
url = https:<span class="hljs-comment">//gitlab.com/codasteroid/basicpkg</span>
project_urls =
    Bug Tracker = https:<span class="hljs-comment">//gitlab.com/codasteroid/basicpkg/-/issues</span>
    repository = https:<span class="hljs-comment">//gitlab.com/codasteroid/basicpkg</span>
classifiers =
    Programming Language :: Python :: <span class="hljs-number">3</span>
    <span class="hljs-attr">License</span> :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
package_dir =
    = src
packages = find:
python_requires = &gt;=<span class="hljs-number">3.6</span>

[options.packages.find]
where = src
</code></pre><p>You should just keep everything as default in the options category. The package_dir locates the root package where your packages, modules, and all your Python source files are located. </p>
<p>In the packages key, we can list our packages manually like this <code>[divide, multiply]</code>. But if we want to get all the packages, we can use <code>find:</code> and specify where we need to find these packages by using <code>[options.packages.find]</code> with the <code>where</code> key assigned to the name of the root package.</p>
<p>Always make sure to include the <code>classifiers</code> key in your configuration file to add some important information like the version of Python and the operating system our package is suitable for. You can find the complete list of classifiers <a target="_blank" href="https://pypi.org/classifiers/">here</a>.</p>
<h3 id="heading-create-pyprojecttoml">Create pyproject.toml</h3>
<p>We will be using setuptools as a build system. To tell <code>pip</code> or other build tools about our build system, we need two variables, as seen below. </p>
<p>We use <code>build-system.require</code> to include what we need to build our package, while <code>build-system.build-back-end</code> defines the object that will perform the build. </p>
<p>So, let's enter the following content in <code>pyproject.toml</code>:</p>
<pre><code>[build-system]
requires = [<span class="hljs-string">'setuptools&gt;=42'</span>]
build-backend = <span class="hljs-string">'setuptools.build_meta'</span>
</code></pre><p>Note that you can safely move all configuration settings in <code>setup.cfg</code> to <code>pyproject.toml</code> if you decide to change the build system to flit or poetry, for example. This will save you time.</p>
<h3 id="heading-create-the-readmemd">Create the README.md</h3>
<p>Creating a good <code>README.md</code> is important. Let's add a description to our package, and include some instructions on how to install it:</p>
<pre><code class="lang-markdown"><span class="hljs-section"># `basicpkg`</span>

The <span class="hljs-code">`basicpkg`</span> is a simple testing example to understand the basics of developing your first Python package.
</code></pre>
<p>We can also add how to use our package like this:</p>
<pre><code class="lang-markdown">from multiply.by<span class="hljs-emphasis">_three import multiply_</span>by<span class="hljs-emphasis">_three
from divide.by_</span>three import divide<span class="hljs-emphasis">_by_</span>three

multiply<span class="hljs-emphasis">_by_</span>three(9)
divide<span class="hljs-emphasis">_by_</span>three(21)
</code></pre>
<p>Feel free to add any information that can help other devs understand what your package is used for and some instructions on how to install it and work properly with it. </p>
<p>Note that our configuration file will load the <code>README.md</code> and will be included when we distribute our package.</p>
<h3 id="heading-add-a-license">Add a license</h3>
<p>It's very important to add a LICENSE to your project to let users know how they can use your code. Let's choose an MIT license for our Python package and add the following content to <code>LICENSE.txt</code>:</p>
<pre><code>MIT License

Copyright (c) [year] [fullname]

Permission is hereby granted, free <span class="hljs-keyword">of</span> charge, to any person obtaining a copy <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> software and associated documentation files (the <span class="hljs-string">"Software"</span>), to deal <span class="hljs-keyword">in</span> the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies <span class="hljs-keyword">of</span> the Software, and to permit persons to whom the Software is furnished to <span class="hljs-keyword">do</span> so, subject to the following conditions:

The above copyright notice and <span class="hljs-built_in">this</span> permission notice shall be included <span class="hljs-keyword">in</span> all copies or substantial portions <span class="hljs-keyword">of</span> the Software.

THE SOFTWARE IS PROVIDED <span class="hljs-string">"AS IS"</span>, 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.
</code></pre><p>Don't forget to replace [year] with the current year and [full name] with your name or the names of the copyright holders.</p>
<h3 id="heading-generate-the-distribution-archives">Generate the distribution archives</h3>
<p>One more step left to get our package ready for distribution: generating the distribution archives for our Python package. To do so, first we need to update our PyPA's build and then generate the source and built archives.</p>
<p>In the terminal/cmd, run the following commands from the same directory where the <code>pyproject.toml</code> file is located:</p>
<p>For Linux:</p>
<pre><code>python3 -m pip install --upgrade build
python3 -m build
</code></pre><p>For Windows:</p>
<pre><code>py -m pip install --upgrade build
py -m build
</code></pre><p>Once the process above is completed, a new directory is generated called <code>dist/</code> with two files in it. The <code>.tag.tz</code> file is the source archive and the <code>.whl*</code> file is the built archive. These files represent the distribution archives of our Python package which will be uploaded to the Python Package Index and installed by <code>pip</code> in the following sections.</p>
<h2 id="heading-how-to-upload-a-package-in-python">How to upload a package in Python</h2>
<p>Python Package Index is where we should upload our project. Since our Python package is in test and we might add other functionalities to experiment with it, we should use a separate instance of PyPI called TestPyPI. This instance is specifically implemented for testing and experimentation. Then, once your package is ready and meets your expectations, you can upload it to PyPI as a real package.</p>
<p>Let's follow the instructions below to get our TestPyPI ready to upload our package:</p>
<ol>
<li>Go to <a target="_blank" href="https://test.pypi.org/">TestPyPI</a> and create an account.</li>
<li>Verify your email address so you can upload packages.</li>
<li>Update your profile settings (add your picture and so on).</li>
<li>Go to <a target="_blank" href="https://test.pypi.org/manage/account/#api-tokens">api-tokens</a> and create your API token to securely upload your packages.</li>
<li>On the same page, set the scope to "entire account".</li>
<li>Copy and save your token in a safe place on your disk.</li>
</ol>
<p>Next, we need to upload our distribution archives. To do so, we have to use an upload tool to upload our package. The official PyPI upload tool is <strong>twine</strong>, so let's install twine and upload our distribution archives under the <code>dist/</code> directory.</p>
<p>In the terminal/cmd, run the following commands from the same directory where the <code>pyproject.toml</code> file is located:</p>
<p>For Linux:</p>
<pre><code>python3 -m pip install --upgrade twine
python3 -m twine upload --repository testpypi dist<span class="hljs-comment">/*</span>
</code></pre><p>For Windows:</p>
<pre><code>py -m pip install --upgrade twine
py -m twine upload --repository testpypi dist<span class="hljs-comment">/*</span>
</code></pre><p>Then, enter <code>__token__</code>. as username, and the token (pypi- prefix included) you saved as a password. Press Enter to upload the distributions.</p>
<h2 id="heading-how-to-install-the-uploaded-python-package">How to install the uploaded Python package</h2>
<p>Now, it's time to install our package. You can create a new virtual environment and use <code>pip</code> to install it from TestPyPI:</p>
<p>For Linux:</p>
<pre><code>python3 -m venv env
source env/bin/activate
(env) python3 -m pip install --index-url https:<span class="hljs-comment">//test.pypi.org/simple/ --no-deps basicpkg</span>
</code></pre><p>For Windows:</p>
<pre><code>py -m venv env
.\env\Scripts\activate
(env) py -m pip install --index-url https:<span class="hljs-comment">//test.pypi.org/simple/ --no-deps basicpkg</span>
</code></pre><p>Make sure your virtual environment is activated before you verify if our package works properly. </p>
<p>In the terminal/command, run <code>python3</code> for Linux users or run <code>py</code> for Windows users. Then, type the following code to make sure that the multiply and divide packages work as expected:</p>
<pre><code><span class="hljs-keyword">from</span> multiply.by_three <span class="hljs-keyword">import</span> multiply_by_three
<span class="hljs-keyword">from</span> divide.by_three <span class="hljs-keyword">import</span> divide_by_three

multiply_by_three(<span class="hljs-number">9</span>)
divide_by_three(<span class="hljs-number">21</span>)

# Output: <span class="hljs-number">27</span>
# Output: <span class="hljs-number">7</span>
</code></pre><p>Remember that we need to import the methods from our modules that we need to perform the desired operations, as we did above.</p>
<p>Hooray! Our package works as expected.</p>
<p>So, once you test and experiment with your package, follow the instructions below to upload your package to the real PyPI:</p>
<ol>
<li>Go to <a target="_blank" href="https://pypi.org/">PyPI</a> and create an account.</li>
<li>Run <code>twine upload dist/*</code> in the terminal/command line.</li>
<li>Enter the account credentials you registered for on the actual PyPI.</li>
<li>Then, run <code>pip install [package_name]</code> to install your package.</li>
</ol>
<p>Congratulations! Your package was installed from the real PyPI.</p>
<h2 id="heading-whats-next">What's next?</h2>
<p>It would be great if you come up with a simple idea and build with it your first real Python package. In this blog post, I focused only on the basics you need to get started, but there is a lot to learn in the world of packaging. </p>
<p>Hopefully, my first experience with developing Python packages helps you learn what you need to get building. If you have any questions, feel free to connect and hit me up at any time on <a target="_blank" href="https://www.linkedin.com/in/rochdi-khalid/">LinkedIn</a>. Also, you can subscribe to my <a target="_blank" href="https://www.youtube.com/channel/UCF8iZXSsjgc8kE8hITp5rdQ">channel</a> on YouTube where I share videos on what I'm learning and building with code.</p>
<p>See you in the next post and keep moving forward!</p>
<h3 id="heading-references">References</h3>
<p>Here are some references that helped me develop my first Python package:</p>
<ul>
<li><a target="_blank" href="https://packaging.python.org/en/latest/tutorials/packaging-projects/">Packaging Python Projects</a></li>
<li><a target="_blank" href="https://packaging.python.org/en/latest/tutorials/packaging-projects/#configuring-metadata">Configuring metadata</a></li>
<li><a target="_blank" href="https://peps.python.org/pep-0621/#example">PEP 621 – Storing project metadata in pyproject.toml</a></li>
<li><a target="_blank" href="https://packaging.python.org/en/latest/glossary/#term-Source-Archive">Glossary - Python Packaging User Guide</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
