My favorite Python packages!
Tags: python, tooling, opensource, discuss
Published: 2022-12-14 18:39:40

Python has a rich ecosystem of packages and tools. Because of its versatility, all manner of helper packages, command line tools, and rich libraries have been built. I have been coding in Python since 2012, and I’ve seen the ecosystem grow considerably. From dependency management, database ORMs, and server solutions, here are my favorite Python packages of 2022!

## Arrow

### Because `datetime` has always sucked.

[Arrow](https://arrow.readthedocs.io/en/latest/) is a package that makes working with dates in Python as easy as a single line of code - and not a complicated one either. Say you have a date string from your web app, `2013-05-11T21:23:58.970460+07:00`. This can be converted with a single line of code using arrow, with no complicated formatting:

```python
import arrow

date_one_str = '2013-05-11T21:23:58.970460+07:00'
date_one = arrow.get(date_one_str)
```

Need it as a datetime?

```python
date_one_dt = date_one.datetime
```

Need the time right now?

```python
now = arrow.now()
```

Need to convert from a datetime to an arrow time object?

```python
arrow_obj = arrow.get(datetime_obj)
```

Need to get time from a string with formatting?

```python
arrow_obj_two = arrow.get('2013-05-05 12:30:45', 'YYYY-MM-DD HH:mm:ss')
```

Need to format your arrow object?

```python
date_one.format('YYYY-MM-DD HH:mm:ss ZZ')
# or even just
date_one.format() # if you just want a pretty string.
```

Need human readable strings?

```python
date_one.humanize()
```

Need to shift time?

```python
date_two = date_one.shift(hours=2, minutes=3)
# negatives are also acceptable
date_three = date_one.shift(years=-1)
# timezones are also a thing
date_four = date_one.to('US/Pacific')
```

Need to get from epoch?

```python
# arrow assumes seconds for numbers
date_five = arrow.get(1661268857)
# floats work too
date_six = arrow.get(166126884.9243)
```

Now Tom Scott can be less [angry about timezones](https://youtu.be/-5wpm-gesOY). Or you can just use UTC like a normal dev.

## OpenCV

### What if your programs need to see?

Now this library is so big and versatile that I’m not giving you examples, but I will link you to some cool projects that use it. [OpenCV](https://pypi.org/project/opencv-python/) is a [computer vision](https://en.wikipedia.org/wiki/Computer_vision) library that was originally built for C but has wrappers for all manner of languages, with the most popular being Python. This allows you to take in video or image input from either a file, a webcam, or even a live video stream over the internet. You can then process each image using various techniques to get information from those images. Information can be as simple as an average color, or as complex as finding specific targets within the image.

This *is not* a small library, needing potentially gigabytes libraries depending on your OS configuration. It is also not the fastest when you are running big calculations, and will need heavy optimizations to keep framerates high if processing video. 

- [Casual Coders’ Autoturret Project](https://github.com/CasualCodersProjects/autoturret)
- [Sudoku solver](https://github.com/1nfinityLoop/Sudoku-Solver-AI)

If you need some tutorials, [Awesome OpenCV](https://github.com/CasualCodersProjects/autoturret) has a massive list of books and online tutorials - both free and paid - to help you get started. 

## FastAPI

### When you just need an API that’s fast.

If you have ever worked with micro frameworks like Flask or Sinatra, you will feel right at home with [FastAPI](https://fastapi.tiangolo.com/). Built to be as fast as possible, FastAPI allows you to make all manner of Python web applications - from simple APIs to massive full stack web applications. Using Python [Dataclasses](https://docs.python.org/3/library/dataclasses.html) as well as [type hinting](https://docs.python.org/3/library/typing.html), it can make your API as close to idiot proof as possible. It even has support for OpenAPI, as well as auto generated documentation. Here an example of a super minimal FastAPI application.

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}
```

That’s it! Python dictionaries are automatically converted to valid JSON objects when returned. 

## SQLModel

### Now you can make APIs, how about some data to serve?

[SQLModel](https://sqlmodel.tiangolo.com/) is a library for interacting with SQL databases from Python code, using Python objects. It is designed to be intuitive, easy-to-use, highly compatible, and robust. It is powered by [Pydantic](https://pydantic-docs.helpmanual.io/) and [SQLAlchemy](https://sqlalchemy.org/) and relies on Python type annotations for maximum simplicity. The key features are: it's intuitive to write and use, highly compatible, extensible, and minimizes code duplication. The library does a lot of the work under the hood to make writing code easier and eliminate the need to duplicate models in SQLAlchemy and Pydantic.

Its compatibility with Pydantic means that any models you write for SQLModel also natively work with FastAPI! Here are some snippets from the official docs.

```python
from typing import Optional

from sqlmodel import Field, SQLModel

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: Optional[int] = None
```

And here is an example of using FastAPI with SQLModel.

```python
from typing import Optional

from fastapi import FastAPI
from sqlmodel import Field, Session, SQLModel, create_engine, select

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: Optional[int] = Field(default=None, index=True)

sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"

connect_args = {"check_same_thread": False}
engine = create_engine(sqlite_url, echo=True, connect_args=connect_args)

def create_db_and_tables():
    SQLModel.metadata.create_all(engine)

app = FastAPI()

@app.on_event("startup")
def on_startup():
    create_db_and_tables()

@app.post("/heroes/")
def create_hero(hero: Hero):
    with Session(engine) as session:
        session.add(hero)
        session.commit()
        session.refresh(hero)
        return hero

@app.get("/heroes/")
def read_heroes():
    with Session(engine) as session:
        heroes = session.exec(select(Hero)).all()
        return heroes
```

They’re a perfect pairing for any sort of CRUD application written in Python!

## Conclusion

Do you have any Python packages you use daily? Let me know in the comments! Thanks for reading!