Cpt*_*rkt 74 python module path package python-2.7
我已经看过各种各样的例子和其他类似的问题,但我似乎无法找到一个与我的场景完全匹配的例子.我觉得这总是一个问题,因为有很多类似的问题,但我似乎无法让这个工作"正确".这是我的项目:
user_management (package)
|
|------- __init__.py
|
|------- Modules/
| |
| |----- __init__.py
| |----- LDAPManager.py
| |----- PasswordManager.py
|
|------- Scripts/
| |
| |----- __init__.py
| |----- CreateUser.py
| |----- FindUser.py
Run Code Online (Sandbox Code Playgroud)
如果我将"CreateUser.py"移动到主user_management目录,我可以轻松地使用:"import Modules.LDAPManager"导入LDAPManager.py ---这可行.我不能做的(我想做的)是将CreateUser.py保存在Scripts子文件夹中,然后导入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
Run Code Online (Sandbox Code Playgroud)
我听说这是不好的做法而且气馁.
脚本中的文件是直接执行的(脚本中的init .py甚至是必要的吗?).我已经读过,在这种情况下,我应该使用-m标志执行CreateUser.py.我已经尝试了一些变体,似乎无法让CreateUser.py识别LDAPManager.py.
Bak*_*riu 61
如果我移动
CreateUser.py到主user_management目录,我可以轻松使用:import Modules.LDAPManager导入LDAPManager.py---这是有效的.
拜托,不要.通过这种方式,LDAPManager所用模块CreateUser将不会是一样的一个通过其他进口进口.当您在模块中有一些全局状态或在酸洗/去除涂层期间,这可能会产生问题.避免仅仅因为模块恰好位于同一目录中而导致的导入.
当你有一个包结构时,你应该:
使用相对导入,即如果CreateUser.py是Scripts/:
from ..Modules import LDAPManager
Run Code Online (Sandbox Code Playgroud)
请注意,PEP 8不鼓励这一点(注意过去时),因为旧版本的python不能很好地支持它们,但这个问题在几年前就解决了.PEP 8 的当前版本确实表明它们是绝对进口的可接受替代品.我实际上喜欢它们在包内.
使用整个包名称(CreateUser.pyin Scripts/)使用绝对导入:
from user_management.Modules import LDAPManager
Run Code Online (Sandbox Code Playgroud)为了使第二个工作,包user_management应该安装在里面PYTHONPATH.在开发期间,您可以配置IDE以便发生这种情况,而无需手动将调用添加到sys.path.append任何位置.
另外我觉得奇怪的Scripts/是它是一个子包.因为在实际安装中,user_management模块将安装在目录中的site-packages找到的位置lib/(用于在操作系统中安装库的目录),而脚本应安装在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
Run Code Online (Sandbox Code Playgroud)
然后代码CreateUser.py和FindUser.py应该使用绝对导入来导入模块:
from user_management.Modules import LDAPManager
Run Code Online (Sandbox Code Playgroud)
在安装过程中,确保user_management最终PYTHONPATH位于目录中的某个位置,以及可执行文件的目录中的脚本,以便它们能够找到模块.在开发过程中你要么依靠IDE配置,或在启动CreateUser.py添加Scripts/父目录的PYTHONPATH(我是指既包含目录user_management和Scripts):
PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py
Run Code Online (Sandbox Code Playgroud)
或者您可以PYTHONPATH全局修改,这样您就不必每次都指定它.在unix操作系统(Linux,Mac OS X等)上,您可以修改其中一个shell脚本来定义PYTHONPATH外部变量,在Windows上您必须更改环境变量设置.
附录我相信,如果您使用的是python2,最好通过放置以下内容来确保避免隐式相对导入:
from __future__ import absolute_import
Run Code Online (Sandbox Code Playgroud)
在模块的顶部.这样import X 总是意味着导入顶层模块X,永远不会尝试导入X.py同一目录中的文件(如果该目录不在其中PYTHONPATH).通过这种方式,进行相对导入的唯一方法是使用显式语法(the from . import X),这更好(显式优于隐式).
这将确保你永远不会碰巧使用"虚假"的隐式相对进口,因为这会引发一个ImportError明确的信号,即出现问题.否则你可以使用一个不是你认为的模块.
jon*_*rpe 14
从Python 2.5开始,您可以使用
from ..Modules import LDAPManager
Run Code Online (Sandbox Code Playgroud)
领先时期会让你"升级"到你的层次结构中.
请参阅有关导入的包内引用的Python文档.
在“根”中,__init__.py您还可以执行
import sys
sys.path.insert(1, '.')
Run Code Online (Sandbox Code Playgroud)
这应该使两个模块都可以导入。
| 归档时间: |
|
| 查看次数: |
90085 次 |
| 最近记录: |