Python module and package tutorial: from "heap of code" to "structural expert"
When we first start learning Python, we always like to cram all functions, variables, and logic into itmain.py——写个爬虫、做个计算器感觉还挺爽。 But once the code grows to hundreds or thousands of lines, or when you want to reuse a certain tool function that you have written before, trouble comes: variable name conflict (both functions haveget_total), I couldn’t find the function after searching for a long time, and I didn’t dare to delete or change the code, for fear of disturbing my whole body.
At this time, Module and Package are your savior. They can help you break the code into small units with clear logic, which can be independently reused and avoid naming conflicts.
1. Module: Your first "code storage box"
What is a module?
Simply put, the ** module is a.pyfile**, the file name is its module name (such asmath_utils.pyThe module name ismath_utils)。
It can hold:
- function definition
- variable definition
- class definition
- Some execution statements (but the main logic is recommended not to write too many unless the module is used to run directly)
Core advantages of modules
Splitting large files into modules can bring these four real benefits:
- Easy to maintain: Separate functions such as "mathematical calculations", "file operations" and "data formatting". Next time you make changes, only the corresponding small files will be moved and other logic will not be affected.
- Reusable: The written tool modules can be copied and used directly between different projects, and can also be uploaded to PyPI for others to use.
- Avoid naming conflicts: Different modules can have functions/variables with the same name, just add the module prefix when calling (for example
math_utils.get_totalandsales_utils.get_total)。 - Accelerated loading: After Python imports a module for the first time, it will save the compiled bytecode into
.pycThe file is placed in__pycache__directory, and then directly read the cache when importing without re-parsing the source code.
2. Package: Modular "multi-layer storage rack"
When there are more and more modules (for example, 10 tool modules, 5 data model modules), just putting a bunch of files in a flat directory will be messy - then you need to package and use the directory structure to classify and manage the modules.
What is a package?
A package is essentially a directory, but it is recommended to put a__init__.pyFile (can be empty), used to tell Python: "This is a Python package, not an ordinary folder."
Note: Python 3.3+ supports namespace packages, allowing no
__init__.pypackage, but it is still recommended to keep this file for compatibility and IDE friendliness.
A standard package structure example
The following is the structure of a small e-commerce backend project, which is clear at a glance:
__init__.pyThe three major functions of
Don’t underestimate this file, it can do a lot of things:
- Identity: Compatible with older versions of Python and some development tools.
- Simplified import: Common modules/functions can be exposed at the top level of the package to avoid writing long and smelly sub-paths.
- Control visibility: Pass
__all__list definitionfrom package import *What content will be imported to prevent internal helper functions from polluting the namespace.
Specific usage will be given in the later practical sessions.
3. 4 common ways to import modules/packages
3.1 Absolute import (most recommended)
The absolute path is the clearest and less error-prone no matter where the code is run from. It is the officially recommended method.
3.2 Relative import (only used inside the package)
For relative import.(current directory) and..(Superior directory) Simplifies references within the same project, but it can only be used in files inside the package and cannot be used in entry files outside the package, otherwise an error will be reported:
ValueError: attempted relative import with no known parent package
Example: inecommerce_backend/models/user.pyImport sibling modules or superior packages.
4. How does Python find your module/package?
Sometimes the import will reportModuleNotFoundError, it’s not that the module is really missing, but that Python didn’t find it. If you understand the order of search paths first, you will be able to solve the problem much faster:
- Built-in module: e.g.
os、sys、math, the highest priority. - The directory where the currently running script is located (when running interactively, it is the directory of the current terminal window).
- **
PYTHONPATHDirectory specified by environment variable ** (common project paths can be added manually). - Default path dependent on installation: such as
site-packages(usepip installThe installed third-party libraries are all here).
View the current search path
5. 5 best practices for newbies to avoid pitfalls
5.1 Module/package naming should be standardized
- Use all lowercase + underscores for module names, such as
user_service.py、data_parser.py, do not start with camel case or capital letters. - It is strictly prohibited to have the same name as the standard library or commonly used third-party libraries! For example
os.py、requests.pyIt will overwrite the official modules and cause various weird errors. - Simple check method: Open Python in the terminal and enter
import 你打算用的名字, if no error is reported, it means that the name has been occupied, change it quickly.
5.2 Avoidfrom module import *
This kind of import will dump all the content in the module (even internal auxiliary functions) into the current namespace, which is prone to conflicts and difficult to trace the source. Unless in the package__init__.pyChinese use__all__The scope is clearly defined, otherwise its use is not recommended.
5.3 Place the import statement in the right position
- Put them all at the top of the file.
- Group them in the order of standard library → third-party library → local module/package, with a blank line between each group to make it look clearer.
5.4 Useif __name__ == '__main__'Do unit testing
After each module is written, you can add test code, so that the test will only be executed when the module is run directly, and will not be triggered when it is imported.
5.5 The package structure should be as “flat” as possible
Try to avoid more than 3 levels of nested packages (e.g.a/b/c/d.py), otherwise the import path will be long and difficult to maintain. If the functionality is really thin, you can consider splitting it into multiple independent packages, or using namespace packages to manage it.
6. Practical combat: Build a small tool kit from scratch
Let's create a simplesimple_toolsThe toolkit contains two sub-modules, string and mathematics, and then use the entry file to test it.
6.1 Final package structure
6.2 Core code
(1)simple_tools/str_utils.py(String Tools Module)
(2)simple_tools/math_utils.py(Mathematical Tools Module)
(3)simple_tools/__init__.py(simplify import + define visibility)
(4)main.py(entry test file)
6.3 Running tests
Open in terminalsimple_tools_demoDirectory, execute:
You can see all test results and verify that our toolkit is working properly.
7. Module Easter Eggs in Modern Python
7.1 Namespace package (Python 3.3+)
If you have multiple directories and want them to share a package name (such as a plug-in system), you can completely delete all related directories.__init__.py, Python will automatically merge them into a namespace package to achieve cross-directory package merging.
7.2 Clean module cache
Sometimes the module code is modified, but the old result is still the same when running the entry file - this is because.pycThe cache is not refreshed. The manual cleaning method is very simple:
- Delete the directory where the module is located
__pycache__folder. - or execute in Python
import importlib; importlib.reload(你的模块名)(It is only recommended for debugging, do not add formal code).
Summarize
Modules and packages are the cornerstone of building large-scale projects in Python. The core idea is: split the code into small units with clear logic, classify them according to the directory structure, and use standardized import methods to call.
Now hurry up and get your thousand-linemain.pyTake it apart and you will find that the joy of writing code is back 😎

