杰瑞科技汇

Python如何导入另一个Python文件?

核心概念:模块

在 Python 中,每一个 .py 文件都可以被称为一个 模块,当你导入一个文件时,你实际上是在导入它的模块。

Python如何导入另一个Python文件?-图1
(图片来源网络,侵删)

假设你有以下两个文件,它们位于同一个文件夹 my_project 中:

文件结构:

my_project/
├── my_module.py      # 这是我们要导入的模块文件
└── main_script.py    # 这是我们要运行的主脚本文件

导入同一目录下的模块

这是最常见、最简单的情况。

my_module.py (被导入的文件)

这个文件包含一些可以被其他文件使用的代码,比如变量、函数或类。

Python如何导入另一个Python文件?-图2
(图片来源网络,侵删)
# my_module.py
# 定义一个变量
MODULE_CONSTANT = "Hello from my_module!"
# 定义一个函数
def greet(name):
    """打印一个问候语"""
    print(f"Welcome, {name}! This is a function from my_module.")
# 定义一个类
class Calculator:
    def add(self, a, b):
        return a + b

main_script.py (执行导入的文件)

这个文件会导入并使用 my_module.py 中的内容。

方法 A:导入整个模块

使用 import module_name 语句。

# main_script.py
# 导入整个 my_module 模块
import my_module
# --- 使用模块中的内容 ---
# 1. 访问模块中的变量
print(my_module.MODULE_CONSTANT)
# 2. 调用模块中的函数
my_module.greet("Alice")
# 3. 使用模块中的类
calc = my_module.Calculator()
result = calc.add(10, 5)
print(f"The result of the calculation is: {result}")

如何运行: 打开终端或命令行,进入到 my_project 目录,然后运行:

Python如何导入另一个Python文件?-图3
(图片来源网络,侵删)
python main_script.py

输出:

Hello from my_module!
Welcome, Alice! This is a function from my_module.
The result of the calculation is: 15

方法 B:导入特定成员

如果你只需要模块中的某个函数或变量,可以使用 from ... import ... 语句,这样就不需要每次都写模块名前缀。

# main_script_v2.py
# 从 my_module 中只导入 greet 函数和 MODULE_CONSTANT 变量
from my_module import greet, MODULE_CONSTANT
# --- 直接使用导入的成员,无需模块名前缀 ---
print(MODULE_CONSTANT)
greet("Bob")
# 如果尝试使用 Calculator,会报错 NameError,因为我们没有导入它
# calc = Calculator() 

方法 C:导入所有成员

使用 from ... import * 会导入模块中所有不以下划线 _ 开头的公共成员。

# main_script_v3.py
# 导入 my_module 中的所有公共成员
from my_module import *
print(MODULE_CONSTANT)
greet("Charlie")
calc = Calculator()
print(calc.multiply(4, 3)) # 假设 my_module.py 中有 multiply 方法

⚠️ *`import 的警告**: 虽然import *` 看起来很方便,但它通常被认为是不好的实践,原因如下:

  1. 命名空间污染:它会把所有导入的名称都扔到当前文件的全局命名空间中,容易与你自己定义的变量或函数发生冲突。
  2. 代码可读性差:当别人(或未来的你)阅读代码时,很难快速知道某个变量或函数是从哪里来的。
  3. 难以维护my_module.py 更新了,增加了新的公共成员,你的代码可能会在不知不觉中受到意想不到的影响。

最佳实践:优先使用 import modulefrom module import specific_item,尽量避免使用 import *


导入不同目录下的模块

当你的项目变大,模块会分布在不同的文件夹中,这时就需要稍微复杂一点的导入方式。

项目结构调整

让我们把项目结构调整一下,增加一个 utils 文件夹。

my_project/
├── main_script.py
└── utils/
    ├── __init__.py      # !!!关键文件
    └── string_utils.py  # 存放字符串相关工具的模块

关键点:要让 Python 将一个文件夹识别为一个 ,这个文件夹中必须包含一个名为 __init__.py 的文件,这个文件可以为空,它的作用是告诉 Python “这个目录是一个 Python 包”。

utils/string_utils.py (子目录下的模块)

# utils/string_utils.py
def reverse_string(text):
    """反转一个字符串"""
    return text[::-1]
def capitalize_words(text):
    """将字符串中的每个单词首字母大写"""
    return ' '.join(word.capitalize() for word in text.split())

main_script.py (导入子目录下的模块)

我们从 main_script.py 导入 utils 包中的 string_utils

# main_script.py
# 方法 A: 导入整个包,然后使用包名.模块名 访问
import utils.string_utils
reversed_text = utils.string_utils.reverse_string("Python is fun")
print(f"Reversed text: {reversed_text}")
# 方法 B: 从包中导入特定的模块
from utils import string_utils
capitalized_text = string_utils.capitalize_words("hello world of python")
print(f"Capitalized text: {capitalized_text}")
# 方法 C: 从模块中导入特定的函数 (推荐)
from utils.string_utils import reverse_string, capitalize_words
# 现在可以直接使用函数了
print(f"Directly using function: {reverse_string('direct call')}")

导入项目根目录外的模块

你可能想导入一个不在项目当前目录或子目录中的模块,你有一个共享的工具库 shared_lib 在项目之外。

/path/to/my_project/
└── main_script.py
/path/to/shared_lib/
└── helper.py

helper.py 的内容:

# /path/to/shared_lib/helper.py
def do_something():
    print("Doing something from the shared library!")

main_script.py 的内容:

# /path/to/my_project/main_script.py
# 直接导入会失败: ModuleNotFoundError: No module named 'shared_lib'
# import shared_lib.helper 
# 解决方案:将共享库的父目录添加到 sys.path
import sys
import os
# 获取 shared_lib 的绝对路径
# 假设 main_script.py 在 /path/to/my_project/
# shared_lib 在 /path/to/shared_lib/
# 那么我们需要添加的路径是 /path/to/
project_root = os.path.dirname(os.path.abspath(__file__))
shared_lib_parent_dir = os.path.dirname(project_root) # 向上两级到 /path/to/
# 将路径添加到 sys.path
sys.path.append(shared_lib_parent_dir)
# 现在可以成功导入了
from shared_lib import helper
helper.do_something()

更优雅的解决方案(推荐): 对于大型项目,强烈建议使用 虚拟环境包管理工具(如 pip),你可以将 shared_lib 打包成一个标准的 Python 包(使用 setup.py),然后通过 pip install . 将其安装到你的 Python 环境中,之后,你就可以像导入任何第三方库(如 requests, numpy)一样直接导入了,无需修改 sys.path


总结与最佳实践

场景 示例 说明
同一目录 import my_module
from my_module import my_func
最基本、最常用。
子目录 (包) import utils.string_utils
from utils import string_utils
子目录必须有 __init__.py 文件才能成为包。
项目外部 sys.path.append('/path/to/module_parent')
from my_module import my_func
临时解决方案,不推荐用于大型项目。
第三方库 import requests 通过 pip install 安装后,直接导入即可。

核心原则:

  1. 明确性:代码应该清晰地表明它的依赖关系。import modulefrom module import specific_itemimport * 更好。
  2. 避免命名冲突:不要给模块、函数或变量起与标准库或第三方库相同的名字(不要创建一个名为 os.py 的文件)。
  3. 组织代码:将相关的功能组织到同一个模块(.py 文件)中,将相关的模块组织到同一个包(文件夹)中,使项目结构清晰。
  4. 使用虚拟环境:为每个项目创建独立的虚拟环境,可以避免不同项目之间的包版本冲突,并简化依赖管理。
分享:
扫描分享到社交APP
上一篇
下一篇