从不同文件夹导入文件

从不同文件夹导入文件

技术背景

在Python编程中,当需要使用其他文件夹中的模块或文件时,就涉及到从不同文件夹导入文件的问题。默认情况下,Python在导入文件时,仅会搜索入口脚本所在的目录以及sys.path中包含的位置(如包安装目录)。

实现步骤

运行时添加Python路径

在运行时,可以通过修改sys.path来添加额外的搜索路径。示例代码如下:

1
2
3
4
5
6
# some_file.py
import sys
# caution: path[0] is reserved for script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')

import file

同时,要确保目标文件夹中包含__init__.py文件,使其能作为包被包含。

平行位置模块导入

当模块处于平行位置时,可使用如下代码使一个模块对另一个模块可见:

1
2
import sys
sys.path.append('../')

使用相对导入

相对导入通过在导入语句前添加点号来指定相对路径。例如:

1
from ...app.folder.file import func_name

每个前导点表示在层次结构中向上一级,从当前目录开始。

利用PYTHONPATH环境变量

在不同操作系统中设置PYTHONPATH的方法不同:

1
2
3
4
5
# Linux and OS X
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%

Python 3.4及更高版本直接从源文件导入

可以使用importlib.util模块直接从源文件导入模块,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import importlib.util

def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module

foo = module_from_file("foo", "/path/to/foo.py")

if __name__ == "__main__":
print(foo)
print(dir(foo))
foo.announce()

使用os.path获取完整路径

当应用程序的文件夹结构固定时,可使用os.path来获取要导入模块的完整路径。示例如下:

1
2
3
4
5
import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

创建包并使用绝对导入

创建一个包,并使用绝对导入来访问包中的其他模块。示例文件夹结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
package/
├── __init__.py
├── main_module.py
├── module_0.py
├── subpackage_1/
| ├── __init__.py
| ├── module_1.py
| └── sub_subpackage_3/
| ├── __init__.py
| └── module_3.py
└── subpackage_2/
├── __init__.py
└── module_2.py

main_module.py中使用绝对导入:

1
import subpackage_1.module_1

核心代码

以下是一个简单的相对导入示例:

1
2
3
4
5
6
7
# main.py
from myfolder.myfile import myfunc
myfunc()

# myfolder/myfile.py
def myfunc():
print('hello')

最佳实践

  • 优先使用包和绝对导入,因为这样可以使代码更具可读性和可维护性。
  • 避免在生产环境中使用运行时修改sys.path的方法,因为这可能会导致代码在不同环境中出现问题。
  • 在Python 3.3及更高版本中,由于存在隐式命名空间包,子目录中可以不使用__init__.py文件。

常见问题

  • 相对导入报错:如果相对导入不起作用,可能是因为遇到了相对导入的许多陷阱。确保每个目录级别都有__init__.py文件,并尝试使用python -m命令从顶级目录运行脚本。
  • sys.path修改问题:使用sys.path.append添加绝对路径在将应用程序迁移到其他环境时可能不理想,而使用相对路径又依赖于脚本的调用方式。可以使用os.path来解决这个问题。

从不同文件夹导入文件
https://119291.xyz/posts/2025-05-13.importing-files-from-different-folder/
作者
ww
发布于
2025年5月13日
许可协议