在实例化队列之前缺少 multiprocessing.queue 模块 [英] multiprocessing.queue module is missing until a Queue is instanced
问题描述
我正在Queues
工作,一切似乎都很顺利.但是,我发现一种情况会导致出现意外的 AttributeError
异常.
I was working witch Queues
and everything seemed to go fine. However, I found a situation that makes an unexpected AttributeError
exception to arise.
让我们创建最简单的代码来创建Queue
.不用担心它的用法,这一切都发生在同一端,我们不必担心另一端会与之通信.
Let's create the simplest code to create a Queue
. Don't worry about it's usage, it all happens in the same side, we don't have to worry about the other side that will communicate with it.
import multiprocessing
q = multiprocessing.Queue()
print(type(q))
此代码将作为输出产生:
This code will produce as output:
<class 'multiprocessing.queues.Queue'>
但是如果我尝试确定对象是否是此类的实例会发生什么?
But what happens if I try to identify if the object is an instance of this class?
isinstance(q, multiprocessing.queues.Queue)
显然它返回True
.
最后,我的问题是因此而产生的,如果我在检查之前不创建 Queue
实例,模块 multiprocessing.queues
where Queue
已定义,未加载!(警告,因为我们谈论的是模块,所以这里可能不适合使用加载这个词.我不是这方面的专家)让我们检查一下:
Finally, my question arose due to that, if I don't create a Queue
instance before that checking, the module multiprocessing.queues
where Queue
is defined, is not loaded! (Warning, maybe loaded is not the appropriate word here since we are talking about modules. I'm not an expert on it) Let's check it:
import multiprocessing
a = dict()
isinstance(a, multiprocessing.queues.Queue)
出乎意料的是我们失败的地方:
Where surprisingly we get the failure:
1 isinstance(a, multiprocessing.queues.Queue)
AttributeError: module 'multiprocessing' has no attribute 'queues'
为什么会这样?这是预期的行为还是这种错误?
对我来说,这代表了一个问题,因为如果我想检查一个对象是否是 Queue
而它不是,如果没有其他队列被实例化,我的检查可能以不需要的 AttributeError
.
For me, this represents a problem because in case I want to check if an object is a Queue
and it's not, if no other queue has been instanced my check could end in an undesired AttributeError
.
最后,我想添加一个快速图片,其中包含一些我复制的检查,并在 multiprocessing.__all__
中添加了一些对 queues
模块的检查.
Finally, I would like to add a quick picture with some checks that I did reproducing this, plus adding some checks for the queues
module inside the multiprocessing.__all__
.
这些检查已在 Python 3.9.1 中执行.值得注意的是,当 multiprocessing.queues
已经被识别并且因此检查没有抛出 AttributeError
时,queues
出现在 <代码>multiprocessing.__dict__.在其他情况下,则不是.
These checks have been performed in Python 3.9.1. It is worth noting that, when multiprocessing.queues
was already recognized and therefore the checks didn't throw the AttributeError
, queues
was present in multiprocessing.__dict__
. In the other cases, it is not.
这对专家来说似乎很自然,因为 __dict__
是(AFAIK)属性列表,但我想指出它,因为我说过我不是专家,我不不知道它的实际含义.
This may seem natural to the expert eye, since __dict__
is (AFAIK) a list of attributes, but I wanted to point it out since as I said I'm not an expert and I don't know the actual implications of it.
附注.我已将问题标记为 Python 3.8
,因为它已在 3.8
和 3.9
中进行了测试,结果相同,以防有差异我想要3.8
的答案.这些差异可能是由于多处理库的变化而出现的,因为文档反映在函数末尾的几个脚注中.
PS. I've tagged the question as Python 3.8
since it has been tested in both 3.8
and 3.9
with same results, and in case there are differences I would like the answer for 3.8
. Those differences are likely to appear due to multiprocessing library changes as the docs reflects in several footnotes at the end of the functions.
PS.2.由于 multiprocessing.__dict__
的输出,我一直将 multiprocessing.queues
称为模块.再说一次,我不是这方面的专家:
PS.2. I've been referring to multiprocessing.queues
as a module due to the output of multiprocessing.__dict__
. Again I'm not an expert on the matter:
'queues': <module 'multiprocessing.queues' from 'C:\\Program Files\\Python39\\lib\\multiprocessing\\queues.py'>
推荐答案
这是预期行为.如果你想访问一个子模块,你应该导入它:
This is intended behaviour. If you want to access a submodule, you should import it:
import multiprocessing.queues
a = dict()
isinstance(a, multiprocessing.queues.Queue)
导入子模块会将它们作为属性添加到其父模块中——注意 multiprocessing.queues.Queue
如何是 queue
上的 Queue
的嵌套属性查找> queue
在 multiprocessing
之后.显式导入可确保在访问子模块之前加载它.
Importing submodules adds them as attributes to their parent module – note how multiprocessing.queues.Queue
is a nested attribute lookup of Queue
on queue
after queue
on multiprocessing
. An explicit import ensures the submodule will be loaded before accessing it.
当使用任何机制(例如 importlib
API、import
或 import-from
语句或内置 __import__()
) 一个绑定被放置在父模块的命名空间中到子模块对象.比如包spam
有一个子模块foo
,导入spam.foo
后,spam
就会有一个属性foo
绑定到子模块.
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.
这意味着当另一个操作作为副作用导入子模块时,可以避免跳过显式导出.与所有副作用一样,人们必须实际执行触发动作才能依赖副作用.
This means one can get away skipping an explicit export when another action imports the submodule as a side effect. As with all side effects, one has to actually perform the triggering action in order to rely on the side effect.
由于导入是幂等的(重复导入不会产生不良影响),因此应该导入任何希望访问的模块,而不是依赖其他代码的副作用.
Since imports are idempotent (repeating them has no ill effect), one should import any module one expects to access instead of relying on side effects of other code.
这篇关于在实例化队列之前缺少 multiprocessing.queue 模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!