无法让 Python 从不同的文件夹导入

问题描述 投票:0回答:9

我似乎无法让 Python 在子文件夹中导入模块。当我尝试从导入的模块创建类的实例时出现错误,但导入本身成功了。这是我的目录结构:

Server
    -server.py
    -Models
        --user.py

这里是server.py的内容:

from sys import path
from os import getcwd
path.append(getcwd() + "\\models") #Yes, i'm on windows
print path
import user

u=user.User() #error on this line

和用户.py:

class User(Entity):
    using_options(tablename='users')

    username = Field(String(15))
    password = Field(String(64))
    email    = Field(String(50))
    status   = Field(Integer)
    created  = Field(DateTime)

错误是: AttributeError:“模块”对象没有属性“用户”

python python-2.x
9个回答
164
投票

我相信您需要在 Models 目录中创建一个名为

__init__.py
的文件,以便 python 将其视为一个模块。

然后你可以这样做:

from Models.user import User

您可以在

__init__.py
中包含代码(例如一些不同类需要的初始化代码)或将其留空。但它必须在那里。


28
投票

您必须在

__init__.py
子文件夹上创建
Models
。该文件可能为空。它定义了一个包。

然后你可以这样做:

from Models.user import User

在 python 教程中阅读所有相关内容,这里.

还有一篇关于 python 项目的文件组织的好文章这里.


13
投票

导入用户

u=user.User() #这一行出错

由于缺少上面提到的 __init__,您会期望一个 ImportError 使问题更清楚。

你没有得到一个,因为'user'也是标准库中的现有模块。您的 import 语句抓住了那个并试图在其中找到 User 类;那不存在,只有这样你才会得到错误。

绝对导入通常是个好主意:

import Server.Models.user

避免这种歧义。实际上,从 Python 2.7 开始,“导入用户”根本不会相对于当前模块。

如果你真的想要相对导入,你可以在 Python 2.5 和更高版本中使用有点丑陋的语法明确地使用它们:

from .user import User

11
投票

当您没有标准的包结构时,导入位于父文件夹中的模块的正确方法是:

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))

(你可以合并最后两行,但这种方式更容易理解)。

本方案跨平台,通用性强,其他情况下无需修改


8
投票

你缺少 __init__.py。来自 Python 教程:

需要 __init__.py 文件 使 Python 将目录视为 包含包裹;这是为了 防止具有共同的目录 名称,例如字符串,来自 无意中隐藏有效模块 稍后在模块搜索中发生 小路。在最简单的情况下, __init__.py 可以只是一个空文件,但它也可以执行初始化 代码包或设置 __all__ 变量,稍后描述。

在你的 Models 目录中放一个名为 __init__.py 的空文件,一切都应该是金色的。


1
投票

你怎么写出参数

os.path.dirname
....命令?

import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))

0
投票

我的首选方法是在每个包含被其他模块使用的模块的目录上都有 __init__.py,并在入口点覆盖 sys.path,如下所示:

def get_path(ss):
  return os.path.join(os.path.dirname(__file__), ss)
sys.path += [
  get_path('Server'), 
  get_path('Models')
]

这使得指定目录中的文件对导入可见,我可以从 Server.py 导入用户。


0
投票

在仔细阅读以上这些贡献者给出的答案后 - Zorglub29、Tom、Mark、Aaron McMillin、lucasamaral、JoeyZhao、Kjeld Flarup、Procyclinsur、martin.zaenker、tooty44 并调试了我面临的问题,我发现了一个不同的问题由于我面临这个问题的用例。 因此,在下面添加我的观察以供任何人参考。

在我的代码中,我循环导入了类。例如:

src
 |-- utilities.py (has Utilities class that uses Event class)  
 |-- consume_utilities.py (has Event class that uses Utilities class)
 |-- tests
      |-- test_consume_utilities.py (executes test cases that involves Event class)

当我尝试执行 python -m pytest tests/test_utilities.py 以执行用 test_utilities.py 编写的 UT 时,出现以下错误

ImportError while importing test module '/Users/.../src/tests/test_utilities.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_utilities.py:1: in <module>
    from utilities import Utilities
...
...
E   ImportError: cannot import name 'Utilities'

我解决错误的方法是重构我的代码以移动循环导入类中的功能,这样我就可以删除类的循环导入。

注意,我的“

src
”文件夹和“tests”文件夹中都有__init__.py文件,并且仍然能够通过重构代码来摆脱“ImportError”。

以下 stackoverflow 链接提供了更多关于 Python 中的循环依赖 的详细信息。


0
投票
在根目录下创建 start.py 或任意名称的 python 文件并添加以下行

import os, sys CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.dirname(CURRENT_DIR))
它会在系统路径变量中添加你的项目根目录路径。添加后,Python 会尝试搜索此路径和默认路径下的所有文件和库。

Note: I have tested this locally. I don't think it is not required on the cloud.


    

© www.soinside.com 2019 - 2024. All rights reserved.