无法从子文件夹运行Python3脚本//相对导入错误

时间:2018-09-10 17:29:17

标签: python python-3.x

我有一个简单的项目结构,如下所示:

➜  (venv:evernote) evernote_bear_project git:(master) ✗ tree | grep -v pyc
.
├── README.md
...
(snip)
...
├── manage.py
├── sample
│   ├── EDAMTest.py    <==== here is an import that won't work
│   └── enlogo.png
└── util
    ├── __init__.py
    ├── files.py        <====== This is being imported
    └── test_files.py

现在我在sample/EDAMTest.py中有一个相对重要的地方:

from ..util.files import * 

当我尝试在命令行中从项目根文件夹运行python sample/EDAMTest.py时,出现错误消息:

ValueError: attempted relative import beyond top-level package

我知道这个问题已经问了很多遍了,但是我还是不明白。

由于我是从项目根目录运行脚本,因此,根据我的理解,Python应该能够“知道”当我尝试导入from ..util.files import *时,脚本应该向上移动{{ 1}},不是吗?


编辑

感谢所有答案。

所以我从链接above中了解的是:

我直接通过directory运行模块sample/EDAMTest.py,这意味着

  1. 该模块的python sample/EDAMTest.py__name__
  2. 现在可以说,路径(__main__)是我的“根”。

因此,现在Python仅搜索此路径及其下的任何路径以查找模块/软件包。因此,错误消息sample/由于它已经在根目录上了,因此它不能再上一层。

Python也无法在“上”一级查找,因为此语法attempted relative import _beyond top-level package_ 不在目录中上一级,但是在模块/软件包列表中,它始终位于“导入搜索路径”(sys.path)?

对吗?

3 个答案:

答案 0 :(得分:0)

sys.path.append()是一个调整,如果您的目录结构是固定的,那么您将无能为力。

否则,您可以尝试重新排列文件夹。最简单的方法是将util移至sample下,另一个选择是将两个文件夹的psrt都设置为较大的包。

也未检查import *

答案 1 :(得分:0)

相对导入语法用于从同一软件包而不是文件系统中导入其他模块。

根据您的需求,您可以...

修复软件包,以便相对导入起作用

__init__.py文件放在项目根目录和示例目录中,并从上一层运行脚本。这似乎不是您想要的。

告诉python在哪里找到软件包

设置PYTHONPATH环境变量,以便python可以找到软件包。

PYTHONPATH='.':$PYTHONPATH python samples/EDAMTest.py

安装util,以便python可以找到它

添加设置脚本并使用它来安装util软件包,并避免设置PYTHONPATH。

答案 2 :(得分:0)

“相对导入语法用于从同一软件包而不是从文件系统中导入其他模块。”,正如乔治·G所说的那样。

Put __init__.py in your subfolders, which will make them package.

__init__.py can be an empty file but it is often used to perform 
setup needed for the package(import things, load things into path, etc).

However you can import File into your __init__.py to make it 
available at the package level:

 # in your __init__.py
 from util import files

 # now import File from util package
 from util import files
 of if you want to import some specific method or class, you can do 
 from util.files import some_function


Another thing to do is at the package level make util/modules 
available   with the __all__ variable. When the interpeter sees 
an  __all__ variable defined in an __init__.py it imports the 
modules listed in the __all__ variable when you do:

from package import *

__all__ is a list containing the names of modules that you want to be
imported with import * so looking at our above example again if we 

希望使用 all 变量导入子模块    在util / init .py中为:

 __all__ = ['files', 'test_files']

With the __all__ variable populated like that, when you perform

 from util import *

它将导入文件和test_files。