我有这样的文件夹结构:

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

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

from application.app.folder.file import func_name

但它不起作用。


当前回答

创建包的最佳实践是从最高级别目录中的main_module.py等模块运行和访问其他模块。

此结构说明您可以使用顶级目录文件main_module.py来使用和访问子包、父包或同级包和模块。

创建并运行这些文件和文件夹以进行测试:

 package/
    |
    |----- __init__.py (Empty file)
    |------- main_module.py (Contains: import subpackage_1.module_1)        
    |------- module_0.py (Contains: print('module_0 at parent directory, is imported'))
    |           
    |
    |------- subpackage_1/
    |           |
    |           |----- __init__.py (Empty file)
    |           |----- module_1.py (Contains: print('importing other modules from module_1...')
    |           |                             import module_0
    |           |                             import subpackage_2.module_2
    |           |                             import subpackage_1.sub_subpackage_3.module_3)
    |           |----- photo.png
    |           |
    |           |
    |           |----- sub_subpackage_3/
    |                        |
    |                        |----- __init__.py (Empty file)
    |                        |----- module_3.py (Contains: print('module_3 at sub directory, is imported')) 
    |
    |------- subpackage_2/
    |           |
    |           |----- __init__.py (Empty file)
    |           |----- module_2.py (Contains: print('module_2 at same level directory, is imported'))

现在运行main_module.py

输出为

>>>'importing other modules from module_1...'
   'module_0 at parent directory, is imported'
   'module_2 at same level directory, is imported'
   'module_3 at sub directory, is imported'

打开图片和文件注意事项:

在包结构中,如果您想访问照片,请使用最高级别目录中的绝对目录。

假设您正在运行main_module.py,并且希望在module_1.py中打开photo.png。

module_1.py必须包含的内容是:

对的:

image_path = 'subpackage_1/photo.png'
cv2.imread(image_path)

错误:

image_path = 'photo.png'
cv2.imread(image_path)

尽管module1.py和photo.png位于同一目录。

其他回答

下面的代码以Python版本安全的方式导入由路径给定的Python脚本,无论它位于何处:

def import_module_by_path(path):
    name = os.path.splitext(os.path.basename(path))[0]
    if sys.version_info[0] == 2:   
        # Python 2
        import imp
        return imp.load_source(name, path)
    elif sys.version_info[:2] <= (3, 4):  
        # Python 3, version <= 3.4
        from importlib.machinery import SourceFileLoader
        return SourceFileLoader(name, path).load_module()
    else:                            
        # Python 3, after 3.4
        import importlib.util
        spec = importlib.util.spec_from_file_location(name, path)
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
        return mod

我在psutils.test.__init__.py的第1042行psutils代码库中发现了这一点(最新提交时间为2020年10月9日)。

用法示例:

script = "/home/username/Documents/some_script.py"
some_module = import_module_by_path(script)
print(some_module.foo())

重要警告:该模块将被视为顶级模块;从父包中的任何相对导入都将失败。

注:这个答案是针对一个非常具体的问题。对于大多数来自搜索引擎的程序员来说,这不是你想要的答案。通常,您会将文件结构化为包(参见其他答案),而不是修改搜索路径。


默认情况下,您不能。当导入文件时,Python只搜索入口点脚本运行的目录和sys.path,其中包括包安装目录等位置(实际上比这复杂一点,但这涵盖了大多数情况)。

但是,您可以在运行时向Python路径添加:

    # 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

在linux上的python3中为我工作

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  

哇,我没想到会花这么多时间在这上面。以下内容对我有用:

操作系统:Windows 10

Python:v3.10.0

注意:由于我是Python v3.10.0,所以我没有使用__init__.py文件,这对我来说无论如何都不起作用。

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

王旭的第一个解决方案对我有效。为了清楚起见,我将其转发了一个绝对的文件参考:

import sys
sys.path.insert(1, 'C:\\Users\\<Your Username>\\application')
import app2.some_folder.some_file

some_file.hello_world()

替代解决方案:然而,这也对我有效:

import sys
sys.path.append( '.' )
import app2.some_folder.some_file

some_file.hello_world()

虽然,我不明白为什么它会起作用。我以为点是对当前目录的引用。但是,当打印出当前文件夹的路径时,当前目录已列在顶部:

for path in sys.path:
    print(path)

希望有人能在评论中澄清为什么这样做有效。尽管如此,我也希望它能帮助一些人。

您可以使用importlib导入模块,其中您希望使用如下字符串从文件夹中导入模块:

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

这个示例有一个main.py,它是上面的代码,然后是一个名为Scripts的文件夹,然后您可以通过更改scriptName变量从这个文件夹中调用所需的任何内容。然后可以使用脚本引用此模块。例如,如果我在Snake模块中有一个名为Hello()的函数,您可以通过这样做来运行该函数:

script.Hello()

我已经在Python 3.6中测试过了