我有这样的文件夹结构:

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

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

from application.app.folder.file import func_name

但它不起作用。


当前回答

这对我在窗户上有用

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file

其他回答

下面的代码以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())

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

将应用程序移动到其他环境时,使用带有绝对路径的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文档。

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

在我的情况下,我有一个类要导入。我的文件如下:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

在我的主文件中,我通过以下方式包含了代码:

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper

这个问题可能是因为Pycharm

我在使用Pycharm时遇到了同样的问题。我有这个项目结构

skylake\
   backend\
      apps\
          example.py
      configuration\
          settings.py
   frontend\
      ...some_stuff

和example.py中配置导入设置的代码引发导入错误

问题是,当我打开Pycharm时,它认为skylake是根路径,并运行了这段代码

sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])

为了解决这个问题,我只将后端目录标记为源根目录

它解决了我的问题

我正在处理项目a,我希望用户通过pip-install a使用以下文件列表进行安装:

.
├── setup.py
├── MANIFEST.in
└── a
    ├── __init__.py
    ├── a.py
    └── b
        ├── __init__.py
        └── b.py

设置.py

from setuptools import setup

setup (
  name='a',
  version='0.0.1',
  packages=['a'],
  package_data={
    'a': ['b/*'],
  },
)

歧管in

recursive-include b *.*

a/init.py

from __future__ import absolute_import

from a.a import cats
import a.b

a/a.py

cats = 0

a/b/init.py

from __future__ import absolute_import

from a.b.b import dogs

a/b/b.py

dogs = 1

我通过在MANIFEST.in目录下运行以下命令来安装模块:

python setup.py install

然后,在我的文件系统上的一个完全不同的位置上,我可以运行:

import a
dir(a)

这证实了a.ats确实等于0,a.b.dogs确实等于1,正如预期的那样。