Python:从项目层次结构中同一级别的另一个目录导入模块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20075884/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: import module from another directory at the same level in project hierarchy
提问by CptSupermrkt
I've seen all sorts of examples and other similar questions, but I can't seem to find an example that exactly matches my scenario. I feel like a total goon asking this because there are so many similar questions, but I just can't seem to get this working "correctly." Here is my project:
我看过各种各样的例子和其他类似的问题,但我似乎找不到与我的场景完全匹配的例子。我觉得自己是个傻瓜,因为有很多类似的问题,但我似乎无法“正确”地解决这个问题。这是我的项目:
user_management (package)
|
|------- __init__.py
|
|------- Modules/
| |
| |----- __init__.py
| |----- LDAPManager.py
| |----- PasswordManager.py
|
|------- Scripts/
| |
| |----- __init__.py
| |----- CreateUser.py
| |----- FindUser.py
If I move "CreateUser.py" to the main user_management directory, I can easily use: "import Modules.LDAPManager"to import LDAPManager.py --- this works. What I can't do (which I want to do), is keep CreateUser.py in the Scripts subfolder, and import LDAPManager.py. I was hoping to accomplish this by using "import user_management.Modules.LDAPManager.py". This doesn't work. In short, I can get Python files to easily look deeper in the hierarchy, but I can't get a Python script to reference up one directory and down into another.
如果我将“CreateUser.py”移动到主 user_management 目录,我可以轻松使用:"import Modules.LDAPManager"导入 LDAPManager.py --- 这有效。我不能做的(我想做的)是将 CreateUser.py 保留在 Scripts 子文件夹中,然后导入 LDAPManager.py。我希望通过使用"import user_management.Modules.LDAPManager.py". 这不起作用。简而言之,我可以让 Python 文件轻松地在层次结构中更深入地查看,但我无法让 Python 脚本向上引用一个目录并向下引用另一个目录。
Note that I am able to solve my problem using:
请注意,我可以使用以下方法解决我的问题:
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager
I've heard that this is bad practice and discouraged.
我听说这是不好的做法并且不鼓励。
The files in Scripts are intended to be executed directly (is the init.py in Scripts even necessary?). I've read that in this case, I should be executing CreateUser.py with the -m flag. I've tried some variations on this and just can't seem to get CreateUser.py to recognize LDAPManager.py.
Scripts 中的文件旨在直接执行(甚至需要 Scripts 中的init.py 吗?)。我读过,在这种情况下,我应该使用 -m 标志执行 CreateUser.py。我已经尝试了一些变体,但似乎无法让 CreateUser.py 识别 LDAPManager.py。
回答by jonrsharpe
From Python 2.5 onwards, you can use
从 Python 2.5 开始,您可以使用
from ..Modules import LDAPManager
The leading period takes you "up" a level in your heirarchy.
领先时期将您在等级制度中“提升”一个级别。
See the Python docs on intra-package referencesfor imports.
请参阅有关导入的包内引用的 Python 文档。
回答by Bakuriu
If I move
CreateUser.pyto the main user_management directory, I can easily use:import Modules.LDAPManagerto importLDAPManager.py--- this works.
如果我移动
CreateUser.py到主 user_management 目录,我可以轻松地使用:import Modules.LDAPManager导入LDAPManager.py--- 这有效。
Please, don't. In this way the LDAPManagermodule used by CreateUserwill notbe the same as the one imported via other imports. This can create problems when you have some global state in the module or during pickling/unpickling. Avoidimports that work only because the module happens to be in the same directory.
请不要。通过这种方式,LDAPManager所用模块CreateUser将不会是一样的一个通过其他进口进口。当您在模块中或在酸洗/取消酸洗期间有一些全局状态时,这可能会产生问题。避免仅因为模块恰好在同一目录中而起作用的导入。
When you have a package structure you should either:
当你有一个包结构时,你应该:
Use relative imports, i.e if the
CreateUser.pyis inScripts/:from ..Modules import LDAPManagerNote that this was(note the pasttense) discouraged by PEP 8only because old versions of python didn't support them very well, but this problem was solved years ago. The currentversion of PEP 8 doessuggest them as an acceptable alternative to absolute imports. I actually likethem inside packages.
Use absolute imports using the whole package name(
CreateUser.pyinScripts/):from user_management.Modules import LDAPManager
使用相对导入,即如果
CreateUser.py是 inScripts/:from ..Modules import LDAPManager请注意,PEP 8不鼓励这样做(注意过去时)只是因为旧版本的 python 不能很好地支持它们,但是这个问题在几年前就已经解决了。在当前的PEP 8的版本并建议他们以绝对的进口可接受的替代。我实际上喜欢它们在包装内。
使用整个包名(
CreateUser.pyinScripts/)使用绝对导入:from user_management.Modules import LDAPManager
In order for the second one to work the package user_managementshould be installed inside the PYTHONPATH. During development you can configure the IDE so that this happens, without having to manually add calls to sys.path.appendanywhere.
为了让第二个工作,这个包user_management应该安装在PYTHONPATH. 在开发过程中,您可以配置 IDE 以实现这一点,而无需手动向sys.path.append任何地方添加调用。
Also I find it odd that Scripts/is a subpackage. Because in a real installation the user_managementmodule would be installed under the site-packagesfound in the lib/directory (whichever directory is used to install libraries in your OS), while the scripts should be installed under a bin/directory (whichever contains executables for your OS).
我也觉得奇怪的是,这Scripts/是一个子包。因为在实际安装中,user_management模块将安装在目录(用于在操作系统中安装库site-packages的lib/目录)中找到的目录下,而脚本应安装在bin/目录下(以包含操作系统可执行文件的目录为准)。
In fact I believe Script/shouldn't even be under user_management. It should be at the same level of user_management.
In this way you do nothave to use -m, but you simply have to make sure the package can be found (this again is a matter of configuring the IDE, installing the package correctly or using PYTHONPATH=. python Scripts/CreateUser.pyto launch the scripts with the correct path).
事实上,我认为Script/甚至不应该在user_management. 它应该与user_management. 这样你就不会有使用-m,但你只需要确保包可以发现(这又是配置IDE,正确安装包或使用的问题PYTHONPATH=. python Scripts/CreateUser.py与正确的路径启动脚本)。
In summary, the hierarchy Iwould use is:
总之,我将使用的层次结构是:
user_management (package)
|
|------- __init__.py
|
|------- Modules/
| |
| |----- __init__.py
| |----- LDAPManager.py
| |----- PasswordManager.py
|
Scripts/ (*not* a package)
|
|----- CreateUser.py
|----- FindUser.py
Then the code of CreateUser.pyand FindUser.pyshould use absolute imports to import the modules:
随后的代码CreateUser.py,并FindUser.py应使用绝对导入来导入模块:
from user_management.Modules import LDAPManager
During installation you make sure that user_managementends up somewhere in the PYTHONPATH, and the scripts inside the directory for executables so that they are able to find the modules. During development you either rely on IDE configuration, or you launch CreateUser.pyadding the Scripts/parent directory to the PYTHONPATH(I mean the directory that contains both user_managementand Scripts):
在安装过程中,您确保user_management最终位于PYTHONPATH, 和可执行文件目录中的脚本中,以便他们能够找到模块。在开发过程中,您要么依赖 IDE 配置,要么启动CreateUser.py将Scripts/父目录添加到PYTHONPATH(我的意思是包含user_management和的目录Scripts):
PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py
Or you can modify the PYTHONPATHglobally so that you don't have to specify this each time. On unix OSes (linux, Mac OS X etc.) you can modify one of the shell scripts to define the PYTHONPATHexternal variable, on Windows you have to change the environmental variables settings.
或者您可以PYTHONPATH全局修改,这样您就不必每次都指定它。在 unix 操作系统(linux、Mac OS X 等)上,您可以修改其中一个 shell 脚本来定义PYTHONPATH外部变量,在 Windows 上,您必须更改环境变量设置。
AddendumI believe, if you are using python2, it's better to make sure to avoid implicit relative imports by putting:
附录我相信,如果您使用的是 python2,最好通过放置以下内容来确保避免隐式相对导入:
from __future__ import absolute_import
at the top of your modules. In this way import Xalwaysmeans to import the toplevelmodule Xand will never try to import the X.pyfile that's in the same directory (if that directory isn't in the PYTHONPATH). In this way the onlyway to do a relative import is to use the explicitsyntax (the from . import X), which is better (explicit is better than implicit).
在模块的顶部。以这种方式import X始终意味着导入顶层模块,X并且永远不会尝试导入X.py同一目录中的文件(如果该目录不在PYTHONPATH. 通过这种方式进行相对导入的唯一方法是使用显式语法 (the from . import X),这更好(显式优于隐式)。
This will make sure you never happen to use the "bogus" implicit relative imports, since these would raise an ImportErrorclearly signalling that something is wrong. Otherwise you could use a module that's not what you think it is.
这将确保您永远不会碰巧使用“虚假”隐式相对导入,因为这些会发出ImportError明确的信号,表明出现问题。否则,您可能会使用与您认为不同的模块。
回答by rdodev
In the "root" __init__.pyyou can also do a
在“根”中,__init__.py您还可以执行
import sys
sys.path.insert(1, '.')
which should make both modules importable.
这应该使两个模块都可以导入。

