【发布时间】:2014-01-17 20:21:02
【问题描述】:
我正在创建一个包含多个模块的 Python 包。我想确保当我在包中导入模块时,它们仅从包中导入,而不是在包外具有相同名称的东西。
这样做的正确方法是使用相对导入吗?当我将包移动到我机器上的不同位置(或安装在客户机器上的任何位置)时,这是否会干扰?
【问题讨论】:
标签: python python-import relative-import
我正在创建一个包含多个模块的 Python 包。我想确保当我在包中导入模块时,它们仅从包中导入,而不是在包外具有相同名称的东西。
这样做的正确方法是使用相对导入吗?当我将包移动到我机器上的不同位置(或安装在客户机器上的任何位置)时,这是否会干扰?
【问题讨论】:
标签: python python-import relative-import
现代的相对导入 (here's a reference) 是相对于包和特定于包的,因此只要包的内部结构不改变,您就可以将包作为一个整体移动到任何地方。
虽然Joran Beasley's answer 应该也可以工作(尽管在那些不是默认绝对导入的旧版本的 Python 中似乎没有必要,因为旧的导入样式首先在包的目录中检查),我个人不真的不喜欢在不需要时修改导入路径,尤其是当您需要加载您的模块或包现在隐藏的一些其他包或模块时。
但是,一个警告:这些确实需要将相关模块作为包的一部分加载,或者至少将它们的__name__ 设置为指示包中的位置。当__name__ == '__main__' 时,相对导入不适用于模块,因此,如果您正在编写一个简单/休闲脚本,该脚本利用与其位于同一目录中的另一个模块(并希望确保脚本将引用正确的目录,如果当前工作目录未设置为脚本,事情将无法正常工作),您可以执行import os, sys; sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) 之类的操作(感谢https://stackoverflow.com/a/1432949/138772 的想法)。正如S.Lott's answer to the same question 中所指出的,这可能不是您想做的专业或团队项目的一部分,但对于您只是在做一些琐碎的任务自动化等个人的事情应该没问题。
【讨论】:
__import__ 函数,该函数确实允许路径规范 iirc)。
if __name__ == '__main__': 功能。从您的评论来看,如果我使用相对进口,我似乎无法做到这一点。对吗?
__init__.py 来做事等),你总是可以在有条件的。最简单的方法可能是将__name__ 设置为导入模块以供导入__main__ 的任何模块的包使用时的实际值,这可能会让您摆脱其中的一些问题。至少,如果它成为一个问题,我可能会这样做。
sys.path 告诉 python 在哪里寻找导入
添加
import sys
sys.path.insert(0,".")
到您的主要 python 脚本的顶部,这将确保在内置包之前导入本地包(尽管我认为这是自动发生的)
如果你真的想只导入文件夹中的包
import sys
sys.path = ["."]
但是我确实不推荐这个,因为它可能会破坏你的很多东西......
大多数 IDE (eclipse/pycharm/etc) 提供了设置项目使用的环境(包括其路径)的机制
最好的选择是不要将软件包命名为与系统上安装的内置软件包或 3rd 方模块相同的名称
最好的选择是通过正确捆绑的包分发它,这应该足够了
【讨论】:
from Myapp_Users import User 例如