Python

Image of Author
October 17, 2023 (last updated September 21, 2024)

Machine setup

Python is undergoing a shift in project management tooling. It is a slow shift that has occurred over the course of years, and will take years more to complete. In v3.12 distutils was removed for reasons discussed in PEP 632. The preference is now for setuptools (or another "build backend") to be used instead.

asdf

Ensure you have python on your machine. I use asdf for language version management in general

asdf plugin add python
asdf install python $(asdf latest python)
asdf global python $(asdf latest python)

Create a python project directory. I'll call this example one proj

mkdir proj
cd proj

venv

Setup venv, which isolates your project changes from your global python environment. venv is library module included in most Python installations. You run library modules via python -m. The below command creates a venv/ folder within your project for storing project-only virtual environment details. (It is also common to call it ./.venv/ if you prefer.)

python -m venv ./venv

You can then activate this environment as follows.

source ./venv/bin/activate

You can confirm this worked by seeing which python you are using before and after activation. Before, it will be your global python, after, it will point to a local python, ./proj/venv/bin/python.

When you are done you can deactivate as follows.

deactivate

While in the virtual environment, calls to pip, etc., only modify the virtual environment.

pyproject.toml, build, and setuptools

Next, install build which is the preferred "build frontend" for the Python ecosystem (to the point where I'm not aware of an alternative). Don't forget to do this in your activated virtual env.

pip install build

Also setup your initial pyproject.toml. This is a relatively new addition to python project management. It was initiated by PEP 518 and PEP 621, with PEP 621 being created as recently as 2020. See the official specification and gentle introduction for more.

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.0.1"
dependencies = [
    "requests",
    'importlib-metadata; python_version<"3.10"',
]

Note the presence of setuptools in the [build-system] section. Setuptools is the "build backend" that build defaults to. build will read the pyproject.toml and use venv and setuptools in it's own environment when building, meaning we don't ever have to pip install setuptools ourselves.

package folder

As per the setuptools quickstart guide, the expected directory structure is a nested folder that is the actual package to be built. It is common to name that directory the same as your parent directory.

/proj/
/proj/pyproject.toml
/proj/README.md
/proj/proj
/proj/proj/__init__.py
# proj/proj/__init__.py

print "hello"

Running python -m build will now build your project. You should get as output a dist/ folder and a mypackage.egg-info/.

Next steps

If you want to upload your project to PyPI, it seems the recommended tool is twine. I haven't ever done this myself so I won't comment much more on it.

If you are just running local projects you don't ever even need to run python -m build, since you aren't distributing it. Certain PaaS environments might not require a dist build either. It might still make sense to make your project installable even if you are building something like a Flask web app.

It seems that pyproject.toml will be the future of Python, so even if you aren't distributing your project, it still makes sense to lean in to these tools, at least as far as I can tell. Relatedly, some of the older solutions are recommending similarly. For example, see the section #Do not use _just_ `pip` and requirements.txt for project management

Do not use just pip and requirements.txt for project management

pip itself has a guide on this topic: Pip is not a workflow management tool. They recommend using tools like build when building, and for package/project/workflow management they recommend the official packaging user guide, which is a core source in my Python#Machine setup notes.

Flask web app

Flask is a web server framework.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
flask run

gunicorn

I don't claim to understand everything going on here, but gunicorn seems to be the default wsgi server. (WSGI appears to be a python web-server-to-web-application interface.)

gunicorn -w 4 'app:app'

pandas

See my note on pandas

Lists

https://docs.python.org/3/library/stdtypes.html#lists

List comprehensions

https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions