multiprocessing.queue 在实例化队列之前缺少模块
multiprocessing.queue module is missing until a Queue is instanced
我在工作 Queues
一切似乎都很顺利。但是,我发现了一种情况,导致出现意外 AttributeError
异常。
让我们创建最简单的代码来创建 Queue
。不用担心它的用法,这一切都发生在同一侧,我们不必担心另一侧会与之通信。
import multiprocessing
q = multiprocessing.Queue()
print(type(q))
此代码将产生输出:
<class 'multiprocessing.queues.Queue'>
但是,如果我尝试确定该对象是否是此 class 的实例,会发生什么情况?
isinstance(q, multiprocessing.queues.Queue)
很明显 returns True
.
最后,我的问题出现了,如果我没有在检查之前创建一个 Queue
实例,则不会加载定义了 Queue
的模块 multiprocessing.queues
! (警告,由于我们谈论的是模块,所以这里可能加载不合适。我不是这方面的专家)让我们检查一下:
import multiprocessing
a = dict()
isinstance(a, multiprocessing.queues.Queue)
令人惊讶的是我们失败了:
1 isinstance(a, multiprocessing.queues.Queue)
AttributeError: module 'multiprocessing' has no attribute 'queues'
为什么会这样?这是预期的行为还是这种错误?
对我来说,这代表了一个问题,因为万一我想检查一个对象是否是 Queue
而不是,如果没有其他队列被实例化,我的检查可能会以不希望的 AttributeError
.
最后,我想添加一张快速图片,其中包含我复制此内容的一些检查,以及在 multiprocessing.__all__
.
中为 queues
模块添加一些检查
这些检查已在 Python 3.9.1 中执行。值得注意的是,当 multiprocessing.queues
已经被识别并且因此检查没有抛出 AttributeError
时,queues
出现在 multiprocessing.__dict__
中。在其他情况下,它不是。
这对专家来说似乎很自然,因为 __dict__
是(AFAIK)属性列表,但我想指出这一点,因为正如我所说,我不是专家,我也不知道不知道它的实际含义。
PS。我已将问题标记为 Python 3.8
,因为它已经在 3.8
和 3.9
中进行了测试,结果相同,如果存在差异,我希望得到 3.8
的答案].由于文档在函数末尾的几个脚注中反映了多处理库的变化,因此可能会出现这些差异。
PS.2。由于 multiprocessing.__dict__
的输出,我一直将 multiprocessing.queues
称为模块。同样,我不是这方面的专家:
'queues': <module 'multiprocessing.queues' from 'C:\Program Files\Python39\lib\multiprocessing\queues.py'>
这是有意为之的行为。如果你想访问一个子模块,你应该导入它:
import multiprocessing.queues
a = dict()
isinstance(a, multiprocessing.queues.Queue)
导入子模块将它们作为属性添加到它们的父模块中——注意 multiprocessing.queues.Queue
是如何在 queue
上 queue
之后 queue
上嵌套属性查找 multiprocessing
=].显式导入确保子模块在访问之前加载。
The import system: 5.4.2. Submodules
When a submodule is loaded using any mechanism (e.g. importlib
APIs, the import
or import-from
statements, or built-in __import__()
) a binding is placed in the parent module’s namespace to the submodule object. For example, if package spam
has a submodule foo
, after importing spam.foo
, spam
will have an attribute foo
which is bound to the submodule.
这意味着当另一个操作作为副作用导入子模块时,可以跳过显式导出。与所有副作用一样,必须实际执行触发操作才能依赖副作用。
由于导入是幂等的(重复它们没有不良影响),因此应该导入任何期望访问的模块,而不是依赖于其他代码的副作用。
我在工作 Queues
一切似乎都很顺利。但是,我发现了一种情况,导致出现意外 AttributeError
异常。
让我们创建最简单的代码来创建 Queue
。不用担心它的用法,这一切都发生在同一侧,我们不必担心另一侧会与之通信。
import multiprocessing
q = multiprocessing.Queue()
print(type(q))
此代码将产生输出:
<class 'multiprocessing.queues.Queue'>
但是,如果我尝试确定该对象是否是此 class 的实例,会发生什么情况?
isinstance(q, multiprocessing.queues.Queue)
很明显 returns True
.
最后,我的问题出现了,如果我没有在检查之前创建一个 Queue
实例,则不会加载定义了 Queue
的模块 multiprocessing.queues
! (警告,由于我们谈论的是模块,所以这里可能加载不合适。我不是这方面的专家)让我们检查一下:
import multiprocessing
a = dict()
isinstance(a, multiprocessing.queues.Queue)
令人惊讶的是我们失败了:
1 isinstance(a, multiprocessing.queues.Queue)
AttributeError: module 'multiprocessing' has no attribute 'queues'
为什么会这样?这是预期的行为还是这种错误?
对我来说,这代表了一个问题,因为万一我想检查一个对象是否是 Queue
而不是,如果没有其他队列被实例化,我的检查可能会以不希望的 AttributeError
.
最后,我想添加一张快速图片,其中包含我复制此内容的一些检查,以及在 multiprocessing.__all__
.
queues
模块添加一些检查
这些检查已在 Python 3.9.1 中执行。值得注意的是,当 multiprocessing.queues
已经被识别并且因此检查没有抛出 AttributeError
时,queues
出现在 multiprocessing.__dict__
中。在其他情况下,它不是。
这对专家来说似乎很自然,因为 __dict__
是(AFAIK)属性列表,但我想指出这一点,因为正如我所说,我不是专家,我也不知道不知道它的实际含义。
PS。我已将问题标记为 Python 3.8
,因为它已经在 3.8
和 3.9
中进行了测试,结果相同,如果存在差异,我希望得到 3.8
的答案].由于文档在函数末尾的几个脚注中反映了多处理库的变化,因此可能会出现这些差异。
PS.2。由于 multiprocessing.__dict__
的输出,我一直将 multiprocessing.queues
称为模块。同样,我不是这方面的专家:
'queues': <module 'multiprocessing.queues' from 'C:\Program Files\Python39\lib\multiprocessing\queues.py'>
这是有意为之的行为。如果你想访问一个子模块,你应该导入它:
import multiprocessing.queues
a = dict()
isinstance(a, multiprocessing.queues.Queue)
导入子模块将它们作为属性添加到它们的父模块中——注意 multiprocessing.queues.Queue
是如何在 queue
上 queue
之后 queue
上嵌套属性查找 multiprocessing
=].显式导入确保子模块在访问之前加载。
The import system: 5.4.2. Submodules
When a submodule is loaded using any mechanism (e.g.
importlib
APIs, theimport
orimport-from
statements, or built-in__import__()
) a binding is placed in the parent module’s namespace to the submodule object. For example, if packagespam
has a submodulefoo
, after importingspam.foo
,spam
will have an attributefoo
which is bound to the submodule.
这意味着当另一个操作作为副作用导入子模块时,可以跳过显式导出。与所有副作用一样,必须实际执行触发操作才能依赖副作用。
由于导入是幂等的(重复它们没有不良影响),因此应该导入任何期望访问的模块,而不是依赖于其他代码的副作用。