简体   繁体   English

无法从其他文件夹导入Python

[英]Can't get Python to import from a different folder

I can't seem to get Python to import a module in a subfolder. 我似乎无法让Python在子文件夹中导入模块。 I get the error when I try to create an instance of the class from the imported module, but the import itself succeeds. 当我尝试从导入的模块创建类的实例时,我收到错误,但导入本身成功。 Here is my directory structure: 这是我的目录结构:

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

Here's the contents of server.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

And user.py: 和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)

The error is: AttributeError: 'module' object has no attribute 'User' 错误是:AttributeError:'module'对象没有属性'User'

I believe you need to create a file called __init__.py in the Models directory so that python treats it as a module. 我相信你需要在Models目录中创建一个名为__init__.py的文件,以便python将其视为一个模块。

Then you can do: 然后你可以这样做:

from Models.user import User

You can include code in the __init__.py (for instance initialization code that a few different classes need) or leave it blank. 您可以在__init__.py包含代码(例如,几个不同类需要的初始化代码)或将其留空。 But it must be there. 但它一定存在。

You have to create __init__.py on the Models subfolder. 您必须在Models子文件夹上创建__init__.py The file may be empty. 该文件可能为空。 It defines a package. 它定义了一个包。

Then you can do: 然后你可以这样做:

from Models.user import User

Read all about it in python tutorial, here . 阅读所有关于它在python教程, 这里

There is also a good article about file organization of python projects here . 还有关于Python项目的文件组织好文章在这里

import user 导入用户

u=user.User() #error on this line u = user.User()#error在这一行

Because of the lack of __init__ mentioned above, you would expect an ImportError which would make the problem clearer. 由于缺少上面提到的__init__,你会发现一个ImportError可以使问题更加清晰。

You don't get one because 'user' is also an existing module in the standard library. 你没有得到一个,因为'user'也是标准库中的现有模块。 Your import statement grabs that one and tries to find the User class inside it; 你的import语句抓住那个并尝试在其中找到User类; that doesn't exist and only then do you get the error. 那是不存在的,只有这样才能得到错误。

It is generally a good idea to make your import absolute: 通常一个绝对的导入是一个好主意:

import Server.Models.user

to avoid this kind of ambiguity. 避免这种模棱两可。 Indeed from Python 2.7 'import user' won't look relative to the current module at all. 事实上,从Python 2.7'导入用户'看起来根本不会与当前模块相关。

If you really want relative imports, you can have them explicitly in Python 2.5 and up using the somewhat ugly syntax: 如果你真的想要相对导入,你可以在Python 2.5中使用稍微丑陋的语法显式地使用它们:

from .user import User

The right way to import a module located on a parent folder, when you don't have a standard package structure, is: 当您没有标准包结构时,导入位于父文件夹的模块的正确方法是:

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

(you can merge the last two lines but this way is easier to understand). (您可以合并最后两行,但这种方式更容易理解)。

This solution is cross-platform and is general enough to need not modify in other circumstances. 该解决方案是跨平台的,并且通用性足以在其他情况下不需要修改。

You're missing __init__.py. 你错过了__init__.py。 From the Python tutorial: 从Python教程:

The __init__.py files are required to make Python treat the directories as containing packages; 需要__init__.py文件才能使Python将目录视为包含包; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. 这样做是为了防止具有通用名称的目录(例如字符串)无意中隐藏稍后在模块搜索路径上发生的有效模块。 In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later. 在最简单的情况下,__ init__.py可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__变量,稍后描述。

Put an empty file named __init__.py in your Models directory, and all should be golden. 将名为__init__.py的空文件放在Models目录中,所有文件都应该是黄金的。

how do you write out the parameters os.path.dirname .... command? 你怎么写出os.path.dirname ....命令的参数?

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

My preferred way is to have __init__.py on every directory that contains modules that get used by other modules, and in the entry point, override sys.path as below: 我首选的方法是在包含其他模块使用的模块的每个目录上都有__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')
]

This makes the files in specified directories visible for import, and I can import user from Server.py. 这使得指定目录中的文件可供导入,我可以从Server.py导入用户。

After going through the answers given by these contributors above - Zorglub29, Tom, Mark, Aaron McMillin, lucasamaral, JoeyZhao, Kjeld Flarup, Procyclinsur, martin.zaenker, tooty44 and debugging the issue that I was facing I found out a different use case due to which I was facing this issue. 在完成上述贡献者给出的答案后 - Zorglub29,Tom,Mark,Aaron McMillin,lucasamaral,JoeyZhao,Kjeld Flarup,Procyclinsur,martin.zaenker,tooty44以及调试我面临的问题我发现了一个不同的用例到期我面对这个问题。 Hence adding my observations below for anybody's reference. 因此,在下面添加我的观察结果供任何人参考。

In my code I had a cyclic import of classes. 在我的代码中,我循环导入了类。 For example: 例如:

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)

I got following error when I tried to execute python -m pytest tests/test_utilities.py for executing UTs written in test_utilities.py. 当我尝试执行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'

The way I resolved the error was by re-factoring my code to move the functionality in cyclic import class so that I could remove the cyclic import of classes. 我解决错误的方法是重新分解我的代码以在循环导入类中移动功能,以便我可以删除类的循环导入。

Note, I have __init__.py file in my ' src ' folder as well as ' tests ' folder and still was able to get rid of the ' ImportError ' just by re-factoring the code. 注意,我的' src '文件夹中有__init__.py文件以及' tests '文件夹,只能通过重新分解代码来摆脱' ImportError '。

Following stackoverflow link provides much more details on Circular dependency in Python . stackoverflow链接之后提供了有关Python中循环依赖的更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM