【问题标题】:Python importing only modules within packagePython仅导入包中的模块
【发布时间】:2014-01-17 20:21:02
【问题描述】:

我正在创建一个包含多个模块的 Python 包。我想确保当我在包中导入模块时,它们仅从包中导入,而不是在包外具有相同名称的东西。

这样做的正确方法是使用相对导入吗?当我将包移动到我机器上的不同位置(或安装在客户机器上的任何位置)时,这是否会干扰?

【问题讨论】:

    标签: python python-import relative-import


    【解决方案1】:

    现代的相对导入 (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 中所指出的,这可能不是您想做的专业或团队项目的一部分,但对于您只是在做一些琐碎的任务自动化等个人的事情应该没问题。

    【讨论】:

    • 我同意他可能不应该在我举的例子中修改它......我试图说清楚:P
    • @JoranBeasley 我主要指的是你答案的第一部分,尽管第二部分没有你想象的那么危险(内置包和模块似乎仍然可用,即使你这样做@ 987654329@,并且您始终可以切换任何必要的导入以使用底层 __import__ 函数,该函数确实允许路径规范 iirc)。
    • 我刚刚意识到,如果当前工作目录在执行期间发生更改,您的版本可能无法正常工作。不过,像 stackoverflow.com/a/1432949/138772 所做的事情会解决这个问题。
    • 在创建/调试我的模块时,我经常使用if __name__ == '__main__': 功能。从您的评论来看,如果我使用相对进口,我似乎无法做到这一点。对吗?
    • @Jeremy 不幸的是,没有,但有一些方法可以解决这个问题(使用模拟包,设置 __init__.py 来做事等),你总是可以在有条件的。最简单的方法可能是将__name__ 设置为导入模块以供导入__main__ 的任何模块的包使用时的实际值,这可能会让您摆脱其中的一些问题。至少,如果它成为一个问题,我可能会这样做。
    【解决方案2】:

    sys.path 告诉 python 在哪里寻找导入

    添加

    import sys
    sys.path.insert(0,".")
    

    到您的主要 python 脚本的顶部,这将确保在内置包之前导入本地包(尽管我认为这是自动发生的)

    如果你真的想只导入文件夹中的包

    import sys
    sys.path = ["."]
    

    但是我确实推荐这个,因为它可能会破坏你的很多东西......

    大多数 IDE (eclipse/pycharm/etc) 提供了设置项目使用的环境(包括其路径)的机制

    最好的选择是不要将软件包命名为与系统上安装的内置软件包或 3rd 方模块相同的名称

    最好的选择是通过正确捆绑的包分发它,这应该足够了

    【讨论】:

    • 我同意将软件包命名为与 3rd 方或内置软件包相同的名称是一个坏主意,但这几乎是不可能的。例如:我不知道别人的机器上会有什么包。
    • 这几乎是不可能的,它应该相对容易避免命名冲突(至少对于内置和大多数 3rd 方模块)......每个开发人员都可以轻松地做到这一点......类名可以相同的只是使用唯一的文件名from Myapp_Users import User 例如
    猜你喜欢
    • 2020-08-27
    • 2016-07-30
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多