我想从同一目录中的另一个文件导入一个函数。

通常,以下工作之一:

from .mymodule import myfunction
from mymodule import myfunction

…但另一个给了我一个错误:

ImportError: attempted relative import with no known parent package
ModuleNotFoundError: No module named 'mymodule'
SystemError: Parent module '' not loaded, cannot perform relative import

这是为什么?


当前回答

将其放入包的__init__.py文件中:

# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

假设您的包是这样的:

├── project
│   ├── package
│   │   ├── __init__.py
│   │   ├── module1.py
│   │   └── module2.py
│   └── setup.py

现在在您的包中使用常规导入,例如:

# in module2.py
from module1 import class1

这在python 2和3中都有效。

其他回答

我需要从主项目目录运行python3才能使其正常工作。

例如,如果项目具有以下结构:

project_demo/
├── main.py
├── some_package/
│   ├── __init__.py
│   └── project_configs.py
└── test/
    └── test_project_configs.py

解决方案

我将在文件夹project_demo/中运行python3,然后执行

from some_package import project_configs

值得注意的是,有时是缓存导致了这一切——在将类重新排列到新目录中之后,我尝试了不同的方法,并且在删除__pycache之后,相对导入开始工作__

将要导入的文件移动到外部目录有帮助。当主文件在其自己的目录中生成任何其他文件时,这是非常有用的。前任:之前:

Project  
|---dir1  
|-------main.py  
|-------module1.py  

之后:

Project  
|---module1.py  
|---dir1  
|-------main.py  

我遇到了这个问题。黑客解决方法是通过if/else块导入,如下所示:

#!/usr/bin/env python3
#myothermodule

if __name__ == '__main__':
    from mymodule import as_int
else:
    from .mymodule import as_int


# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()

我的样板,以使包中的模块具有可独立运行的相对导入。

包/模块.py

## Standalone boilerplate before relative imports
if __package__ is None:                  
    DIR = Path(__file__).resolve().parent
    sys.path.insert(0, str(DIR.parent))
    __package__ = DIR.name

from . import variable_in__init__py
from . import other_module_in_package
...

现在,您可以以任何方式使用模块:

照常运行模块:python-m package.module将其用作模块:python-c“来自包导入模块”独立运行:python package/module.py或者使用shebang(#!/bin/env-python):package/module.py

NB!如果模块与包同名,则使用sys.path.append而不是sys.path.insert将导致难以跟踪的错误。例如my_script/my_script.py

当然,如果您的包层次结构中有较高级别的相对导入,那么这是不够的,但在大多数情况下,这是可以的。