Restructure Your Modules in Python

Intro

If your module becomes too big as you expand your codebase with new features you can restructure it to a package. Let's assume you have a field.py module with below classes;

# db/models/fields.py
...



class OrderWrt(fields.IntegerField):
    ...



class JSONField(CheckFieldDefaultMixin, Field):
    ...



class RelatedField(FieldCacheMixin, Field):
    ...


...

And your directory structure looks like this;

.
└── db
    └── models
        └── fields.py

Solution

You can move your classes to related modules in a fields package;

# db/models/fields/proxy.py
...


class OrderWrt(fields.IntegerField):
    ...
# db/models/fields/json.py
...



class JSONField(CheckFieldDefaultMixin, Field):
    ...
# db/models/fields/related.py
...



class RelatedField(FieldCacheMixin, Field):
    ...

Your package structure now looks like below;

.
└── db
    └── models
        └── fields
            ├── json.py
            ├── proxy.py
            └── related.py

3 directories, 3 files

However this will broke your codebase since all of your imports' paths are false now. In order to fix this import your classes into __init__.py module of your fields package:

# db/models/fields/__init__.py
from db.models.fields.proxy import OrderWrt
from db.models.fields.json import JSONField
from db.models.fields.related import RelatedField

The structure looks like this;

.
└── db
    └── models
        └── fields
            ├── __init__.py
            ├── json.py
            ├── proxy.py
            └── related.py

3 directories, 4 files

Now imports are okay, but if you use flake8 code style and quality tool —you should, now this __init__ module will throw F401 unused errors;

  • (F401) 'db.models.fields.json.JSONField' imported but unused
  • (F401) 'db.models.fields.proxy.OrderWrt' imported but unused
  • (F401) 'db.models.fields.related.RelatedField' imported but unused

We can prevent that by using __all__:

# db/models/fields/___init___.py
from db.models.fields.json import JSONField
from db.models.fields.proxy import OrderWrt
from db.models.fields.related import RelatedField


__all__ = ["JSONField", "OrderWrt", "RelatedField"]

So by this last modification you restructured your big module in a package.

All done!

20