1. Reasons and Benefits of Calling Separate Files in Python
As Programs Grow Larger, Code Splitting Becomes Important
When you first start learning Python, it’s fine to write all the logic in a single file. However, as the code grows, the logic becomes more complex, and managing everything in one file becomes difficult. What becomes important then is the structured approach of defining functions and classes in separate files and calling them as needed. This makes the code more readable and dramatically improves maintainability and reusability.
Increase Code Reusability
For example, there are many functions you might want to reuse across multiple scripts, such as functions that format strings or format dates. If you consolidate such logic into a separate file, you can easily use it in other scripts simply by importing it.
# Defined in utils.py
def format_date(date):
return date.strftime('%Y-%m-%d')
# Called from main.py
from utils import format_date
By doing this, you can reuse code you wrote once as many times as needed, dramatically boosting productivity.
Improved Maintainability and Readability
If you write all logic in a single file, pinpointing the cause of bugs becomes difficult when they occur. It also makes it harder for others to understand the code. When you manage files by functionality,
Database processing is in this file
User input validation is in this file
the responsibilities become clear. As a result,
Bug fixes become faster
Conflicts are reduced even in team development
Code reviews become easier
you gain these benefits.
Essential Skill for Full-Scale Projects
When creating web applications with Python or managing multiple machine‑learning models in a project, splitting files and organizing functionality is a fundamental practice. Even when using frameworks (such as Django or FastAPI), understanding directory structures and the concept of imports is a prerequisite. Therefore, even beginners in Python should acquire the knowledge of “how to call functions or classes from separate files” early on.
2. How to Use Basic Python import Statements
What is an import statement?
In Python, you use the import statement when you want to use functions or classes from other files (modules). Using it, you can call code defined in another file as if it were in the same file. In Python, this mechanism lets you load standard library features or use your own modules.
Basic import for loading files in the same folder
The most basic usage is to import another file located in the same directory. For example, consider the following structure.
project/
├── main.py
└── utils.py
If you want to use a function defined in utils.py from main.py, write it as follows.
In this way, simply specifying the file name lets you use the functions and variables it contains.
When accessing a function, use the “module_name.function_name” format.
Importing specific functions with the from-import syntax
If you only want to use specific functions, you can write them in the form from module_name import function_name.
# main.py
from utils import greet
print(greet("Sagawa"))
Doing so lets you write greet() instead of utils.greet(). Also, you can import multiple functions at once by separating them with commas.
from utils import greet, farewell
Using an alias with import
If a module name is long or you want to simplify it, you can use as to specify an alias.
import utils as ut
print(ut.greet("Sagawa"))
This lets you keep the code concise while preventing conflicts with other modules.
Be careful where you place import statements
In Python, it is generally recommended to place import statements at the top of the file. However, in exceptional cases where a library is only needed at a certain point, you can write the import inside a function.
def use_numpy_temporarily():
import numpy as np
return np.array([1, 2, 3])
Nevertheless, for readability and maintainability, the best practice is to generally consolidate imports at the top.
3. Calling Files from Subdirectories or Other Folders
Import Methods Vary with Folder Structure in Python
When a Python script is split across multiple folders, there are cases where a simple import statement cannot load the file.
In such situations, understanding the correct path specification and the underlying mechanism is necessary.
This section explains how to call functions and classes from files located in subdirectories or other folders, with concrete examples.
Importing Files from a Subdirectory
First, assume a directory structure like the following.
project/
├── main.py
└── tools/
└── formatter.py
If you want to call a function in formatter.py from main.py, you generally write it as follows.
# main.py
from tools import formatter
print(formatter.shout("hello"))
Or, if you only want to use the function:
from tools.formatter import shout
print(shout("hello"))
In this way, you specify the file in a subdirectory using the “directory_name.file_name” syntax.
Sometimes an __init__.py Is Needed to Treat It as a Package
In older Python versions (≤3.2) or some tools, a __init__.py is required to have the subdirectory recognized as a module (package).
tools/
├── __init__.py
└── formatter.py
In this case, simply placing an empty __init__.py file is sufficient. It’s not required in Python 3.3 and later, but including it provides peace of mind.
Importing Files from Parent or Sibling Folders
Now consider importing a file that resides in a different folder. Let’s look at the following layout:
project/
├── main.py
└── modules/
└── helper.py
In this case, Python does not include the modules/ directory in its default search path, so you need to take measures such as the following.
This way, you can add an arbitrary folder to Python’s module search path.
It is especially effective when running the script from the project root.
Solution 2: Pay Attention to Where You Run Python
Python imports are affected by the location from which you run the script (current directory).
Whether you runcode>main.py from within the project/ directory or from modules/ can affect whether the import succeeds.
# Correct way to run
cd project
python main.py
Also, in editors like VSCode, the behavior of the “Run Python File” button can affect the script’s execution path, so be cautious.
Be Aware of the Difference Between Absolute and Relative Imports
from modules.helper import func statements are absolute imports
from ..modules import helper statements are relative imports
Relative imports are convenient, but they tend to raise errors depending on the location of the executing file.
In general, using absolute imports is recommended.
4. Differences between relative and absolute imports and how to choose
There are two types of imports in Python
When calling another file in Python, there are mainly two methods.
Absolute import (absolute import)
Relative import (relative import)
These two have the same purpose, but the syntax and appropriate use cases differ, so it’s important to choose correctly depending on the situation.
What is an absolute import?
An absolute import specifies a module using a path from the project’s root directory. It is the most common and recommended style in many projects.
from tools.formatter import shout
As shown above, you specify it in the form ‘directory_name.file_name.function_name’. Advantages
Easy to read and clear
Runs stably across different execution environments
Makes it easier for other developers to understand the structure
Disadvantages
Can become long (cumbersome in deep hierarchies)
What is a relative import?
A relative import specifies a module relative to the current file’s location. It is mainly used for internal module calls within a package.
from . import formatter # same directory
from ..tools import formatter # one level up
. (dot) refers to the current directory, .. (two dots) indicates one level up. Advantages
Clear relationships within the package
Allows flexible navigation within the same package
Disadvantages
Prone to errors depending on the script’s location
Unsuitable for scripts run directly from outside
Can become hard to read in complex structures
Which should you use? How to choose in practice
Generally, the official Python documentation also recommends the following:
When the library or project is intended to be called from outside: absolute import
For simple module interaction within a package: relative import
Also, for beginners and small to medium-sized projects, using absolute imports as a default reduces trouble.
As shown above, relative imports can raise errors when the script is run as a standalone file.
This happens because Python does not recognize the file as part of a package. In this case, you can avoid it by running it as a module as shown below.
python -m package.module
Conclusion: default to absolute imports, use relative imports as needed
Default to absolute imports (simple, clear, and robust for external use)
Use relative imports only when there are many references within the same package
Relative imports are convenient, but they can become unstable depending on how the script is executed and the development environment.
5. Packaging for Module Management
Organizing Multiple Files: Packaging Is Effective
When developing large-scale programs in Python, properly splitting and organizing files is extremely important.
The concept of packaging is useful in this situation. A package is a collection of modules (Python files) grouped by directory. Grouping multiple functionalities improves readability, maintainability, and reusability dramatically.
init.py: What Is Its Role?
Directories that make up a package generally need to contain a file named __init__.py.
This __init__.py serves as a marker that tells Python to recognize the directory as a package.
Its contents can be empty, but you can also write module initialization code or explicitly specify functions to expose, as shown below.
# tools/__init__.py
from .formatter import shout
This allows callers to import concisely as follows.
from tools import shout
Example Directory Structure
Let’s look at an example of a packaged project structure.
In this case, all modules under tools can be accessed from main.py.
# main.py
from tools import formatter, validator
print(formatter.shout("Hello"))
print(validator.is_valid("12345"))
Summary of Packaging Benefits
Benefit
Description
Easy-to-manage structure
Files can be organized by functionality, improving clarity
Avoid name collisions
Reduces the chance of duplicate module names
Facilitates reuse
Packages can be reused across different projects
Simplifies unit testing and automation
Makes it easier to separate tests by module
Can init.py Be Omitted in Python 3.3+?
Since Python 3.3, directories can be treated as packages even without a __init__.py (Implicit Namespace Package).
However, in practice, it is recommended to include __init__.py for the following reasons.
Some tools or libraries may not support it
You may want to perform explicit initialization within the package
Improves readability and clarity (easier for humans to understand)
Therefore, using __init__.py remains the industry-standard best practice.
6. Common Import Errors and How to Fix Them
Reasons for import failures often stem from a lack of understanding of paths and structure
When trying to call another file in Python, many beginners experience the frustration of errors such as “module not found” or “name not defined.” Here we will specifically introduce common import errors and how to address them.
ModuleNotFoundError: Module not found
Error example:
ModuleNotFoundError: No module named 'utils'
Cause and solution: This error occurs when the specified module is not present in Python’s search path. Common causes include:
The file to be imported does not exist in the same directory or appropriate location
The location of the file being executed is out of sync with the package structure
The module’s path is not included in sys.path
Solution:
Verify the path where the module exists
Unify the execution directory to the root
Add the path with sys.path.append() as needed
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))
ImportError: Module exists but its contents cannot be loaded
Error example:
ImportError: cannot import name 'greet' from 'utils'
Cause and solution: This error occurs when the module itself is found, but the specified function, class, variable, etc., cannot be located. Main causes:
Typo in the filename
The function or class with that name does not actually exist
Because __init__.py does not contain from .module import greet, it is not visible externally
Solution:
Check that the specified name actually exists inside the module
Pay attention to case sensitivity (Python distinguishes it)
Explicitly declare the public interface in __init__.py
Relative import errors: ValueError and ImportError
Cause: This error occurs when a file that uses relative imports is executed directly. When Python runs such a file standalone, it does not recognize it as part of a package. Solution:
When using relative imports, you need to run the file as a module.
# NG: run directly
python script.py
# OK: run as a module
python -m package.script
Best Practices for Avoiding Import Errors
Point
Explanation
Unify script execution location
project/ as the root, and set the “working directory” in VSCode, etc.
Write import statements with absolute paths
Especially for beginners, avoiding relative imports is safer
Use __init__.py to explicitly configure
Package recognition becomes reliable
When temporarily adding to sys.path, specify dynamically with os.path
You can avoid malfunctions caused by environmental differences
7. Practical Code Example: Call and Use Functions from Another File
Let’s Get Hands‑On to Understand
By now, you should have acquired the basic knowledge needed to import another file in Python.
However, ‘understanding’ and ‘being able to use’ are different things. This section will let you learn while working hands‑on,
Splitting files
How to use import statements
How to call functions
Step 1: Create the File that Defines the Function to Be Called
First, create the Python file that will be called.
In this way, you import the utils module and call its greet() function.
Here we use the module name + function name format.
Step 3: Run and Verify the Result
Next, run main.py from a terminal or command prompt.
python main.py
Output:
Hello, Sagawa!
The function from the other file was successfully called, and the intended message was displayed.
Trying Another Import Method (from‑import)
By rewriting as follows, you can call the function more concisely.
# main.py (Improved version)
from utils import greet
print(greet("Sagawa"))
With this method, you can write greet() directly instead of utils.greet().
If you want to use multiple functions, list them separated by commas.
One‑Point Tip for Organizing Code
Common utilities like utils.py can be grouped into directories such as “modules” or “helpers” for easier management.
At a professional level, organizing the directory structure contributes to improved readability and maintainability.
8. FAQ: Common Questions About Importing Python from Separate Files
Q1. What is the difference between import and from ... import ...?
A. Both are ways to load another file, but they differ in how you call them.
import module: loads the entire module and you use it like module.function().
from module import function: loads only a specific function or class, allowing you to call it directly as function().
When using multiple functions or when you want to explicitly show which functions are being used, from ... import ... is convenient.
Q2. Why doesn’t relative import work correctly?
A. Relative imports can cause an error when a module is run on its own. Python does not recognize the file as part of a package.
You can avoid this by executing it as a module, as shown below.
python -m package.module
Also, for beginners, we recommend using absolute imports. They are more stable and less prone to issues.
Q3. I’m unsure how to structure files in Python
A. Generally, the following structure, which separates directories and modules by functionality, is recommended.
Group common code into directories like “utils” or “common”.
Package at the directory level to make extensions easier.
Q4. Is __init__.py always required?
A. Since Python 3.3, packages can function without a __init__.pycode> (Implicit Namespace Packages).
However, it is still recommended to include it for the following reasons.
It makes it explicit that the directory is a package.
Some older tools and certain editors require it.
It can be used for initialization code and to expose public functions.
Since it is widely adopted by development teams and commercial projects, it is generally safer to always include it.
Q5. Can I use file names containing Japanese or special characters when importing?
A. Generally, module names (file names) should only use alphanumeric characters and underscores (_).
For example, the following file names are not allowed:
❌ function.py
❌ utils-mod.py
In Python, the file name becomes the module name, so special characters and hyphens cause errors.
Correct naming examples:
✅ utils.py
✅ data_handler.py
9. Summary: Understanding imports makes Python more flexible
Review of what was learned in this article
So far, this article has explained the following topics step by step:
Why import a separate file? → To organize code and make it reusable
Basic usage of import statements → Choosing between import / from ... import ...
How to import modules from subdirectories or other folders → Understanding path handling and the need for __init__.py
Difference between absolute and relative imports → Absolute imports are recommended for beginners
Common import errors and how to fix them → Most errors stem from execution path and configuration mistakes
Verification with practical code and supplemental FAQ → Covers theory, practice, and common questions
Mastering imports opens up the world of Python
Understanding how imports work and using them correctly provides the following benefits:
You can design a clear structure even for large projects
Consolidate common functionality, making maintenance and updates easier
Easier to understand code written by others
Naturally work with libraries and frameworks (Django, Flask, FastAPI, etc.)
In other words, understanding imports can be described as a gateway for beginners to step beyond the basics.
Conclusion
Python’s simple syntax and flexibility are appealing, but they also demand strong design skills.
By correctly understanding how to import separate files and mastering modules and packages, your code will evolve dramatically. I hope this article helps with your Python learning and professional development.
Feel free to get hands‑on and try out your own module organization.