我可以跨同一个 python 包的模块重用导入吗?

Posted

技术标签:

【中文标题】我可以跨同一个 python 包的模块重用导入吗?【英文标题】:Can I reuse imports across modules of the same python package? 【发布时间】:2021-09-27 10:32:18 【问题描述】:

我有一个名为“test”的包,其中包含多个模块:

master/
|-- __init__.py
|-- app/
|-- auth/
|-- test/
|---- | __ init __.py
|---- | test_A.py
|---- | test_B.py
|---- | test_C.py

所有 test_X.py 都导入相同的核心模块:

import unittest
from unittest.mock import patch
import json
from flask_sqlalchemy import SQLAlchemy

from master.app.app import create_app
from master.app.models import setup_db, subject_student, Subject, Student
from master.app.functions import query_a_record

我想知道是否有一种方法可以创建一个导入所有上述模块并将该文件导入每个测试文件的单个文件。我只是想避免代码重复。

我尝试过的:

在测试包内的 __init __.py 文件中包含所有导入,然后将 init 导入到每个测试中 在包内创建了一个config.py,然后将配置导入到每个模块中。

当然,这些都没有奏效。关于如何只编写一次这些导入并在我的所有测试模块中重用那段代码的任何建议?或者那根本不可能?

【问题讨论】:

【参考方案1】:

我建议您深入研究一下 Python 如何定义和管理 命名空间

至于您的问题,config.py__init__.py 肯定会导入所需的模块,但它们的名称与该命名空间相关联,因此当您在 testX.py 脚本中访问这些名称中的任何一个时,它会引发 NameError因为您在不同的名称空间中并且该名称无法识别;你必须用它所属的模块的名称来限定它。

一个典型的函数调用是:

config.unittest.mock.patch()

您可以通过导入所有 config 命名空间轻松避免此限定:

from config import * 

【讨论】:

非常感谢@MaxShouman。那行得通。在我的情况下,我必须做 from test.config import * 所以,之前,我在 test_X.py 中只尝试了 import config。我在运行 test_X 时遇到的错误不是来自导入配置,而是来自缺少的模块,例如在 config.py 中导入的“unittest”......为什么import config 不起作用?这不是暗示“从配置导入*”吗? 不客气,很高兴它有帮助!顺便说一句,import config 完全符合 from config import * 的解释器方式,但前者按原样加载模块命名空间,而后者提取该命名空间中的所有名称并将它们直接添加到当前命名空间,允许您访问它们而无需资格。实际上,即使您的第一个导入是 from config import unittest,整个 config.py 也会执行并加载到内存中,即使未导入的对象仍然未命名,因此无法访问。 附带说明,from module import * 不是一个好的做法,因为它可能会产生歧义,例如,当您计划在调用脚本中使用相似的名称时。谨慎使用,例如当您确切知道要导入的名称时,或者当您通过在导入的模块中定义 __all__ 变量来明确指定 from module import * 将加载的名称集时。 知道了@MaxShouman。我想在这种特殊情况下我应该是安全的,因为我没有在 config.py 中定义任何函数或类 - 只是导入核心模块来运行测试。如果我将来遇到问题,我想我会猜测它们来自哪里。 @FernandoRodriguez 是的,在这种情况下它绝对是安全的。

以上是关于我可以跨同一个 python 包的模块重用导入吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python类模块包的概念及区别

导入模块方式(尽量少用from xx import *)以及包的定义,跨目录运行包和模块(未完)

Python类模块包的概念及区别

给定 Python 包的名称,要导入的模块的名称是啥?

python中的import

Python 跨目录导入文件问题