【问题标题】:How to import a function in one module to a module in a different folder?如何将一个模块中的功能导入不同文件夹中的模块?
【发布时间】:2021-12-06 09:46:17
【问题描述】:

想象一个具有这种结构的包:

└── main_package
    ├── __init__.py
    ├── subpackage1
    │   ├── __init__.py
    │   └── module1.py
    └── subpackage2
        ├── __init__.py
        └── module2.py

module1 中的函数导入module2 的最佳方法是什么?

__init__.py 文件是否应该包含某些内容?

我发现的最佳解决方案是包含在module2

import sys
sys.path.append('./')
from main_package.subpackage1.module1 import fun1

当从 main_package 所在的目录运行 module2 时。

但我觉得这并没有利用它们是包的事实。如果可能的话,如果能够从我想要的任何地方运行它也会很好。

【问题讨论】:

    标签: python import package


    【解决方案1】:

    最可靠的是始终使用绝对导入。在这种情况下,对于模块 1:

    from MainPackage.module2 import some_function
    

    module1_1 中:

    from MainPackage.Subpackage2.module2_1 import some_function
    

    请注意,包命名约定是所有小写字母,单词之间可以使用下划线(_)。在您的具体示例中,MainPackage 将变为 main_package 等等。

    【讨论】:

    • 首先,感谢您让我了解包命名约定。但这给了我错误“没有名为'MainPackage'的模块”。我可以使用sys.path.append(os.getcwd()),但我尽量避免这种情况。
    • 然后省略MainPackage。例如1:from module2 import some_function.
    • 这适用于第一个问题。这对第二个问题有什么作用?我试过这样的事情:from .. import Subpackage2from ..Subpackage2 import module2_1,......但我得到了错误:ImportError: attempted relative import with no known parent package。我没有找到任何有效的方法。
    • 这不起作用,我收到错误ModuleNotFoundError: No module named 'Subpackage2'。我认为只有当包或模块是您正在处理的文件的兄弟时才允许这样做。
    • 这取决于您执行的文件所在的位置。如果您从根文件夹(一些基本启动脚本)开始,那么它应该可以工作。如果你直接执行module2_1,那确实行不通。那么你的项目结构就没有意义了。
    【解决方案2】:

    第一个问题:

    将模块 1 中的函数导入模块 2 的最佳方法是什么?

    您可以使用相对或绝对导入。就个人而言,我更喜欢在我正在处理的包的上下文中使用相对导入only - 对我来说,当内部包相关时,这会突出显示。此外(这是特定于环境的),某些环境在您安装软件包之前无法识别main_package(即在开发期间使用pip install -e .)。

    模块2中的绝对导入:from main_package.subpackage1.module1 import my_function
    module2 中的相对导入:from ..subpackage1.module1 import my_function

    第二个问题:

    init.py 文件是否应该包含某些内容?

    他们可以,这可能会为您提供导入的快捷方式。在包级别公开通用和/或一流函数/类是常见的做法,本质上只是将它们导入__init__.py
    例如,在subpackage1\__init__.py 中,您可以:

    from .module1 import my_function
    

    然后在subpackage2\module2.py 中,您可以简单地使用from ..subpackage1 import my_function(相对导入)或from main_package.subpackage1 import my_function

    您可能还对原始 Python 文档中的主题感兴趣 - import/submodulesImporting * From a Package(有关导入系统的额外阅读,然后是包内导入)、PEP328(相对导入的基本原理) ) 和Guido's thoughts regardings relative imports

    【讨论】:

    • 非常感谢您的回答。您知道任何无需安装即可识别main_package 的环境吗?
    • 我不知道。 Python 导入系统将在当前工作目录中查找模块,因此如果您从包含 main_package 的文件夹中运行代码,则不会有问题。正如我所提到的,我更喜欢模块内导入的相对导入 - 它清楚地表明 module1module2 是相关的,而不是第 3 方模块的一部分。
    【解决方案3】:

    我认为如果与 Maple 类似,你可以在主模块中导入一个模块或分配一个变量或定义一个函数,然后当你运行主模块时它会自动与所有子模块共享,而不需要再次导入或定义您在子文件中的父文件中已经完成的事情。也许在 Python 中是可能的?

    无论如何,我创建了一个玩具示例。有一个文件夹包含一个 python 文件main.py 和您在问题中显示的包结构。以下是每个文件中写入的内容。

    main.py

    import main_package
    
    main_package.fun2()
    

    main_package__init__.py

    from .subpackage1.module1 import fun1
    from .subpackage2.module2 import fun2
    

    子包的两个init文件为空。

    module1.py

    import sympy
    x = sympy.Symbol('x')
    def fun1(polynomial):
        return(sympy.degree(polynomial, gen = x))
    

    module2.py

    import sympy
    from ..subpackage1.module1 import fun1
    def fun2():
        polynomial = sympy.sympify(input("Type a univariate polynomial with the variable x and integer coefficients:"))
        print(f"Degree of your polynomial in x is {fun1(polynomial)}.")
    

    现在,我不再运行 main_package__init__.py,而是在我的 VSCode 中运行 main.py。请注意,我的 main.py 文件位于 main_package 文件夹旁边,而不是其中。

    再次,我觉得很遗憾我必须在module1.pymodule2.py这两个文件中的每一个中写import sympy,为什么不仅在父顶部__init__.py中,还在那里定义x = sympy.Symbol('x')为好吧。

    【讨论】:

    • 好吧,我刚刚明白了一些事情。为了在名为main_package 的包中访问名为main_function 的函数,您必须将其导入包内的__init__() 文件中,或者您必须使用from main_package import main_function。这可能是微不足道的,但我现在才意识到。
    猜你喜欢
    • 2021-04-20
    • 2022-12-10
    • 1970-01-01
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    相关资源
    最近更新 更多