无法让Python从其他文件夹导入


90

我似乎无法让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

和user.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:'模块'对象没有属性'用户'


1
您可以粘贴错误消息吗?
哈雷·霍尔科姆

如果从user.py,我想导入server.py。我该怎么办?
钱德拉·坎特

Answers:


139

我相信您需要__init__.py在Models目录中创建一个名为的文件,以便python将其视为模块。

然后,您可以执行以下操作:

from Models.user import User

您可以在其中添加代码__init__.py(例如,一些其他类需要的初始化代码),也可以将其留空。但是它必须在那里。


2
谢谢,在此之前我从未听说过软件包。
ryeguy

1
实际上,在导入Python时,blah.py和blah / __ init__.py完全相同。
pi。

2
这并不明显...我对自己说:RTFM FMF
Alexander.Iljushkin

1
请注意,如果您从另一个目录运行server.py,则此方法将无效。
kchoi

1
如果server.py在另一个文件夹中怎么办?
Mandroid

24

您必须__init__.pyModels子文件夹。该文件可能为空。它定义了一个包。

然后,您可以执行以下操作:

from Models.user import User

阅读所有关于它在python教程,这里

还有关于Python项目的文件组织好文章在这里


如果文件不为空怎么办?
darkgaze

12

导入用户

u = user.User()#此行错误

由于缺少上面提到的__init__,因此您可能会期望ImportError,这将使问题更加明确。

您一无所获,因为“用户”也是标准库中的现有模块。您的import语句抓住了那个,并试图在其中找到User类。那不存在,只有这样您才能得到错误。

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

import Server.Models.user

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

如果您确实想要相对导入,则可以使用稍微难看的语法在Python 2.5及更高版本中显式使用它们:

from .user import User

9

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

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

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

该解决方案是跨平台的,通用性很强,无需在其他情况下进行修改。


7

您缺少__init__.py。从Python教程中:

__init__.py文件是使Python将目录视为包含包的必需文件。这样做是为了防止具有通用名称的目录(例如字符串)无意间隐藏了稍后在模块搜索路径中出现的有效模块。在最简单的情况下,__init__.py可以只是一个空文件,但它也可以为该程序包执行初始化代码或设置__all__变量,如后所述。

将一个名为__init__.py的空文件放入您的Models目录中,所有文件都应该是金色的。


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'

解决错误的方法是通过重构代码来移动循环导入类中的功能,以便删除类的循环导入。

注意,__init__.py我的“ src ”文件夹和“ tests ”文件夹中都有文件,但仍然能够摆脱“ ImportError”仅通过重构代码 ”。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.