我似乎无法让 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:“模块”对象没有属性“用户”
我相信您需要在 Models 目录中创建一个名为
__init__.py
的文件,以便 python 将其视为一个模块。
然后你可以这样做:
from Models.user import User
您可以在
__init__.py
中包含代码(例如一些不同类需要的初始化代码)或将其留空。但它必须在那里。
导入用户
u=user.User() #这一行出错
由于缺少上面提到的 __init__,您会期望一个 ImportError 使问题更清楚。
你没有得到一个,因为'user'也是标准库中的现有模块。您的 import 语句抓住了那个并试图在其中找到 User 类;那不存在,只有这样你才会得到错误。
绝对导入通常是个好主意:
import Server.Models.user
避免这种歧义。实际上,从 Python 2.7 开始,“导入用户”根本不会相对于当前模块。
如果你真的想要相对导入,你可以在 Python 2.5 和更高版本中使用有点丑陋的语法明确地使用它们:
from .user import User
当您没有标准的包结构时,导入位于父文件夹中的模块的正确方法是:
import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
(你可以合并最后两行,但这种方式更容易理解)。
本方案跨平台,通用性强,其他情况下无需修改
你缺少 __init__.py。来自 Python 教程:
需要 __init__.py 文件 使 Python 将目录视为 包含包裹;这是为了 防止具有共同的目录 名称,例如字符串,来自 无意中隐藏有效模块 稍后在模块搜索中发生 小路。在最简单的情况下, __init__.py 可以只是一个空文件,但它也可以执行初始化 代码包或设置 __all__ 变量,稍后描述。
在你的 Models 目录中放一个名为 __init__.py 的空文件,一切都应该是金色的。
你怎么写出参数
os.path.dirname
....命令?
import os, sys
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(CURRENT_DIR))
我的首选方法是在每个包含被其他模块使用的模块的目录上都有 __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 导入用户。
在仔细阅读以上这些贡献者给出的答案后 - 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 中的循环依赖 的详细信息。
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.