【发布时间】:2021-02-10 18:14:31
【问题描述】:
我在 Queues 工作,一切似乎都很顺利。但是,我发现一种情况会导致出现意外的AttributeError 异常。
让我们创建最简单的代码来创建Queue。不用担心它的使用,这一切都发生在同一侧,我们不必担心会与它通信的另一侧。
import multiprocessing
q = multiprocessing.Queue()
print(type(q))
此代码将作为输出产生:
<class 'multiprocessing.queues.Queue'>
但是如果我尝试识别对象是否是此类的实例会发生什么?
isinstance(q, multiprocessing.queues.Queue)
显然它返回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'>
【问题讨论】:
-
如果你想使用
multiprocessing.queues,你必须import multiprocessing.queues。依赖其他东西为你做一个子模块导入总是一个坏主意,不仅仅是这个特定的子模块。 -
您能详细说明一下吗?澄清常规模块导入与其子模块的行为方式之间的差异似乎是理解正在发生的事情的关键——而不是导入子模块。将是一个完美的答案。无论如何,感谢您指出这一点,因为更改导入解决了问题中暴露的行为!
标签: python-3.x python-multiprocessing python-3.8