我有这样的文件夹结构:

application
├── app
│   └── folder
│       └── file.py
└── app2
    └── some_folder
        └── some_file.py

如何从file.py或some_file.py中导入函数?我尝试了:

from application.app.folder.file import func_name

但它不起作用。


当前回答

将应用程序移动到其他环境时,使用带有绝对路径的sys.path.append并不理想。使用相对路径并不总是有效的,因为当前工作目录取决于脚本的调用方式。

由于应用程序文件夹结构是固定的,因此我们可以使用os.path获取要导入的模块的完整路径。例如,如果这是结构:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

假设您要导入芒果模块。您可以在vanilla.py中执行以下操作:

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

当然,您不需要mango_dir变量。

要了解其工作原理,请查看以下交互式会话示例:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

并检查os.path文档。

还值得注意的是,使用包时,处理多个文件夹更容易,因为可以使用虚线模块名称。

其他回答

如果从特定路径加载模块的目的是帮助您开发自定义模块,则可以在测试脚本的同一文件夹中创建指向自定义模块根目录的符号链接。对于在该文件夹中运行的任何脚本,此模块引用将优先于以相同名称安装的任何其他模块。

我在Linux上测试了这个,但它应该可以在任何支持符号链接的现代操作系统中运行。

这种方法的一个优点是,您可以指向位于您自己的本地SVC分支工作副本中的模块,这可以大大简化开发周期,并减少管理不同版本模块的故障模式。

我也面临着同样的挑战,尤其是在导入多个文件时,这就是我如何克服的。

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name

尝试Python的相对导入:

from ...app.folder.file import func_name

每个前导点都是从当前目录开始的层次结构中的另一个更高级别。


问题?如果这对你不起作用,那么你可能会被许多gotcha的相对进口产品所蚕食。阅读答案和评论以了解更多详细信息:如何修复“尝试在非包中进行相对导入”,即使使用__init__.py

提示:在每个目录级别都有__init__.py。您可能需要python-m application.app2.some_folder.some_file(去掉.py),它可以从顶层目录运行,也可以在PYTHONPATH中包含该顶层目录。呸!

以防有人仍然需要解决方案,但在上面的答案中没有找到解决方案。这对我有用:

我有这样的文件夹结构:

a
└── b
    ├── c1
    |   └── d
    |       └── a_script.py
    └── c2
        └── a_lib.py

我需要将a_lib.py包含在a_script.py中。这就是我如何解决c2无法识别的错误:

import sys
from pathlib import Path
path_scripts = Path(__file__).resolve().parents[2]
sys.path.append(str(path_scripts))
from c2 import a_lib

没有问题:

from application.app.folder.file import func_name

只需确保文件夹还包含__init__.py,这允许它作为包包含。不知道为什么其他答案都提到了巨蟒。