的Python:从另一个目录在项目层次结构中的同一级别的进口模块的Python:从另一个目录在项目层

2019-05-13 02:57发布

我见过各种各样的例子和其他类似的问题,但我似乎无法找到正是我的情景相匹配的例子。 我觉得自己像一个总打手问这个,因为有这么多类似的问题,但我似乎无法得到这个工作“正常。” 这里是我的项目:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |
        |------- Scripts/
        |           |
        |           |----- __init__.py
        |           |----- CreateUser.py
        |           |----- FindUser.py

如果我动“CreateUser.py”到主user_management目录,我可以很容易地使用: "import Modules.LDAPManager"导入LDAPManager.py ---这个作品。 我不能做什么(这是我想要做的),就是保持CreateUser.py在脚本子文件夹,进口LDAPManager.py。 我希望通过完成这个"import user_management.Modules.LDAPManager.py" 。 这是行不通的。 总之,我可以得到Python文件可以轻松地看在更深的层次,但我不能让一个Python脚本一个目录下,并引用了到另一个。

请注意,我能够解决使用我的问题:

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager

我听说,这是不好的做法和灰心。

在脚本文件的目的是直接执行(在脚本甚至是必要的初始化的.py?)。 我读过,在这种情况下,我应该与-m标志执行CreateUser.py。 我已经试过这方面的一些变化,只是似乎无法得到CreateUser.py识别LDAPManager.py。

Answer 1:

如果我移动CreateUser.py到主user_management目录,我可以很容易地使用: import Modules.LDAPManager导入LDAPManager.py ---这个作品。

不要 。 通过这种方式, LDAPManager通过使用模块CreateUser 不会是一样的一个通过其他进口进口。 当您的模块或酸洗/在unpickle过程中有一定的全局状态这就会产生问题。 避免只是因为模块恰好是在同一个目录中工作的进口。

当你有你要么一个封装结构:

  • 使用相对进口,即如果CreateUser.py是在Scripts/

      from ..Modules import LDAPManager 

    请注意,这 (注意是过去时态)通过劝阻PEP 8只因为Python的旧版本不支持他们很好,但年前的这个问题得到解决。 PEP 8的最新版本建议他们以绝对的进口可接受的替代。 其实我喜欢他们里面包。

  • 使用全包名称使用绝对导入CreateUser.pyScripts/ ):

      from user_management.Modules import LDAPManager 

为了使第二个工作包user_management应安装在内部PYTHONPATH 。 在开发过程中您可以配置IDE所以,出现这种情况,而无需手动添加呼叫sys.path.append任何地方。

此外,我觉得很奇怪, Scripts/是一个子包。 因为在实际安装user_management模块将下安装site-packages中发现lib/目录(取目录用于安装在OS库),而脚本应该一个下安装bin/目录(取其包含可执行文件您的操作系统)。

事实上,我相信Script/甚至不应该在user_management 。 它应该是在同一水平user_management 。 这样,您就不必使用-m ,但你只需要确保包可以发现(这又是配置IDE,正确安装包或使用的问题PYTHONPATH=. python Scripts/CreateUser.py推出使用正确的路径脚本)。


总之, 会使用层次是:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |

 Scripts/  (*not* a package)
        |  
        |----- CreateUser.py
        |----- FindUser.py

随后的代码CreateUser.pyFindUser.py应该使用绝对导入来导入模块:

from user_management.Modules import LDAPManager

安装过程中,确保user_management在什么地方结束PYTHONPATH ,和可执行文件的目录里面的脚本,以便他们能够找到模块。 在开发过程中你要么依靠IDE配置,或在启动CreateUser.py添加Scripts/父目录的PYTHONPATH (我的意思是既包含目录user_managementScripts ):

PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py

或者你可以修改PYTHONPATH全球,这样你就不必指定此各一次。 在UNIX操作系统(在Linux,Mac OS X等),你可以修改shell脚本的一个定义PYTHONPATH外部变量,在Windows上你必须更改环境变量设置。


增编我相信,如果你正在使用python2,这是更好地确保通过将避免隐相对进口:

from __future__ import absolute_import

在您的模块的顶部。 通过这种方式import X 总是意味着要导入的顶层模块X ,绝不会尝试导入X.py文件,该文件在同一目录下(如果该目录不在PYTHONPATH )。 这样做的相对进口的唯一方法是使用显式语法(的from . import X ),这是更好的( 明确优于隐式 )。

这将确保你永远不会发生在使用“假的”隐相对进口,因为这将引发一个ImportError明确的信号,什么是错。 否则,你可以使用一个模块,这是不是你认为它是。



Answer 2:

通过Python 2.5起,您可以使用

from ..Modules import LDAPManager

主导时期带你“上”在你的层次结构的水平。

参见Python文档封装内引用进口。



Answer 3:

在“根” __init__.py你也可以做一个

import sys
sys.path.insert(1, '.')

这将使这两个模块可导入。



文章来源: Python: import module from another directory at the same level in project hierarchy