python - 子线程不能更新父线程变量?
问题描述
我在aiosmtpd/244中发现了一个非常令人困惑的问题,在这里分享我的困惑,以帮助我找到如何解决问题的灵感。
情况
- 两台运行 Red Hat 7.9 的服务器
- 对一个有效,对另一个无效
- 有问题的代码,简化:
>>> from aiosmtpd.controller import Controller
>>> from aiosmtpd.handlers import Sink
>>> cont = Controller(Sink())
>>> cont.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/aiosmtpd/controller.py", line 180, in start
raise RuntimeError("Unknown Error, failed to init SMTP server")
RuntimeError: Unknown Error, failed to init SMTP server
只有在方法结束时仍然为 Nonestart()
self.smtpd
时,才能生成上述 RuntimeError 。
预期流量
start()
-> _run()
->loop.create_server()
然后在第一次连接时:
loop.create_server()
-> _factory_invoker()
->factory()
该属性在以下几行smtpd
中设置:_factory_invoker
try:
self.smtpd = self.factory()
if self.smtpd is None:
raise RuntimeError("factory() returned None")
return self.smtpd
except Exception as err:
self._thread_exception = err
return _FakeServer(self.loop)
self._thread_exception
在这些行中解释:
if self._thread_exception is not None:
raise self._thread_exception
# Defensive
if self.smtpd is None:
raise RuntimeError("Unknown Error, failed to init SMTP server")
如您所见,如果self.smtpd
是None
,那么只有在 中出现错误时才会发生_factory_invoker()
。如果是这样,错误应该已经被捕获并记录在self._thread_exception
. 如果self._thread_exception
是None
,那么_factory_invoker()
已经成功,因此self.smtpd
不可能None
。
我在解决此问题时遇到的主要问题是,在我的所有测试系统(Windows、Ubuntu、OpenSUSE、MacOS 和 FreeBSD)上,我从未遇到过类似的错误。
所以我很难过。我将不胜感激有关解决此问题的任何想法。
解决方案
好吧,显然我被派去追逐野鹅了。
复合因素是因为我在这些行中抑制了所有异常:
try:
self._testconn()
except Exception:
# We totally don't care of exceptions experienced by _testconn,
# which _will_ happen if factory() experienced problems.
pass
结果,一个非常有用的异常self._testconn()
被吞下了。
显然self._testconn()
尝试连接到 的尝试失败host:port
,因此_factory_invoker()
从未被调用。
一旦将try..except
块修改为仅吞咽socket.socket_timeout
,实际问题就出现了,我们可以快速修复它。
这一切都记录在aiosmtpd/244中,因此我不会在这里重复它们 :-)
感谢所有花时间和精力尝试解决这个难题的人!
推荐阅读
- android - Xamarin.Android 找不到样式资源
- plsql - PLSQL 中的过程和函数有什么区别?
- python - python类中的repr vs str - 两者都给出
- c# - 映射是数据层还是逻辑/业务层的一部分?
- c++ - 如何将 int 数组发送到我的着色器
- python - 模拟一个类,但不是它的一个功能
- python-3.x - 在 python 中使用 pandas 读取 html 表
- javascript - 当值为 false 时删除数组中的确切对象
- python - Python 2.7 上的假日应用程序
- java - 在 Java VM 选项中覆盖默认 user.home 时查找它