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

无法从子文件夹//相对导入错误运行Python3脚本,python,python-3.x,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 ├── __

我有这样一个简单的项目结构:

➜  (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
当我试图从命令行中的项目根文件夹中运行
python sample/EDAMTest.py
时,我收到一个错误消息:

ValueError: attempted relative import beyond top-level package
我知道这个问题已经问过很多次了,但我还是不明白

由于我是从项目根目录运行脚本,据我所知,
Python
应该能够“知道”当我尝试从..util.files import*导入
时,它应该上升一个
目录,不是吗


编辑 谢谢你的回答

因此,我从链接中了解到:

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

  • 模块的
    \uuuu name\uuuuu
    \uuuuu main\uuuu
  • 现在路径(
    sample/
    )可以说是我的“根” 所以现在Python只搜索这个路径和它下面的任何路径来查找模块/包。因此,错误消息
    尝试在顶级包之外进行相对导入,因此它不能再上一级,因为它已经在根目录下了

    此外,Python不能“向上”查找一个级别,因为此语法
    from..util.files import*
    在目录中没有向上一个级别,但在模块/包列表中它保留在“导入搜索路径”(sys.path)上

    正确吗?

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

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


    另外,
    import*
    也未启用

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

    取决于你想要什么,你可以

    修复包,使相对导入工作 将
    \uuuu init\uuuuu.py
    文件放在项目根目录和sample目录中,并从一个级别运行脚本。这似乎不是你想要的

    告诉python在哪里可以找到包 设置PYTHONPATH环境变量,以便python可以找到包

    PYTHONPATH='.':$PYTHONPATH python samples/EDAMTest.py
    
    安装
    util
    ,以便python可以找到它 添加一个安装脚本并使用它安装
    util
    软件包,避免设置PYTHONPATH。

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

    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 
    
    想要导入utilall变量中的子模块 在util/init中,.py将是:

     __all__ = ['files', 'test_files']
    
    With the __all__ variable populated like that, when you perform
    
     from util import *
    

    它将导入文件和测试文件。

    感谢您的详细和非常有用的解释。-不过有一点值得注意:它不应该是
    \uuuu init\uuuu.py
    ,而不是
    init.py
    ?不知何故,编辑器忽略了init的破折号。我把一切都写下来了。它解决了你的问题吗?
     __all__ = ['files', 'test_files']
    
    With the __all__ variable populated like that, when you perform
    
     from util import *