小编ros*_*ori的帖子

重新引发Python异常并保留堆栈跟踪

我试图在一个线程中捕获异常并在主线程中重新引发它:

import threading
import sys

class FailingThread(threading.Thread):
    def run(self):
        try:
            raise ValueError('x')
        except ValueError:
            self.exc_info = sys.exc_info()

failingThread = FailingThread()
failingThread.start()
failingThread.join()

print failingThread.exc_info
raise failingThread.exc_info[1]
Run Code Online (Sandbox Code Playgroud)

这基本上起作用并产生以下输出:

(<type 'exceptions.ValueError'>, ValueError('x',), <traceback object at 0x1004cc320>)
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    raise failingThread.exc_info[1]
Run Code Online (Sandbox Code Playgroud)

但是,异常的来源指向第16行,其中发生了重新加注.原始异常来自第7行.如何修改线程以使输出显示:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
Run Code Online (Sandbox Code Playgroud)

python exception stack-trace

53
推荐指数
1
解决办法
1万
查看次数

具有异常处理的Python生产者/消费者

我正在尝试编写一个看似简单的经典生产者实现 - Python中的消费者习语.对于多个较慢的消费者,有一个相对较快的生产者.原则上,使用Queue模块很容易做到这一点,而库文档只有几行代码.

但是,我还希望代码在异常发生时正常工作.如果发生以下任何事情,生产者和所有消费者都应该停止:

  • 生产者因例外而失败
  • 任何消费者都会因例外而失败
  • 用户停止程序(导致KeyboardInterrupt)

在此之后,整个过程应该无法提出初始异常,以通知调用者出错的地方.

主要的挑战似乎是干净地终止消费者线程,而不是最终阻塞join().设置Thread.deamon = True似乎很流行,但据我所知,如果生产者因异常而失败,这会导致资源泄漏.

我设法编写了一个满足我要求的实现(见下文).但是我发现代码比预期的要复杂得多.

是否有更精简的方式来处理这些情况?

以下是一些示例调用以及来自当前实现的最终日志消息:

生产和消费10件物品:

$ python procon.py
INFO:root:processed all items
Run Code Online (Sandbox Code Playgroud)

不产生任何物品:

$ python procon.py --items 0
INFO:root:processed all items
Run Code Online (Sandbox Code Playgroud)

为10个消费者生产5个项目,因此仅使用一些可用的消费者:

$ python procon.py --items 5 --consumers 10
INFO:root:processed all items
Run Code Online (Sandbox Code Playgroud)

按Control-C中断:

$ python procon.py
^CWARNING:root:interrupted by user
Run Code Online (Sandbox Code Playgroud)

未能生产第3项:

$ python procon.py --producer-fails-at 3
ERROR:root:cannot produce item 3
Run Code Online (Sandbox Code Playgroud)

无法使用第3项:

$ python procon.py --consumer-fails-at 3
ERROR:root:cannot consume item 3
Run Code Online (Sandbox Code Playgroud)

无法使用最后一项:

$ python procon.py --items 10 --consumer-fails-at 9
ERROR:root:cannot consume …
Run Code Online (Sandbox Code Playgroud)

python queue multithreading exception-handling

5
推荐指数
1
解决办法
3210
查看次数

如何检测两个Python迭代器产生相同的项目?

是否有一种简洁且内存有效的方法来找出两个迭代器是否lines1产生lines2相同的项目?

例如,这些迭代器可以是从文件对象检索的行:

with io.open(`some.txt`, 'r', encoding='...') as lines1:
  with io.open(`other.txt`, 'r', encoding='...') as lines2:
    lines_are_equal = ...
Run Code Online (Sandbox Code Playgroud)

直觉上人们可以预期

lines_are_equal = lines1 == lines2  # DOES NOT WORK
Run Code Online (Sandbox Code Playgroud)

会给出想要的结果。然而,这始终是False因为它只比较迭代器的地址而不是产生的项目。

如果内存不是问题,可以将迭代器转换为列表并比较它们:

lines_are_equal = list(lines1) == list(lines2)  # works but uses a lot of memory
Run Code Online (Sandbox Code Playgroud)

我已经检查过itertools,希望找到类似的东西

lines_are_equal = itertools.equal(lines1, lines2)  # DOES NOT WORK
Run Code Online (Sandbox Code Playgroud)

但好像没有这样的功能。

到目前为止我能想到的最好的方法是使用itertools.zip_longest()(Python 2:)循环两个迭代器izip_longest()

lines_are_equal = True
for line1, line2 in itertools.zip_longest(lines1, lines2):
  if line1 != line2:
    lines_are_equal …
Run Code Online (Sandbox Code Playgroud)

python iterator compare python-2.7

3
推荐指数
1
解决办法
1653
查看次数

如何在mosquitto MQTT中处理具有相同ID的多个客户端?

如果多个持久订阅者尝试使用相同的客户端 ID 进行连接,我如何告诉 mosquitto MQTT 该怎么做?

在错误配置订阅同一个代理的不同测试环境时,我不小心遇到了这种情况。结果是,两个订阅者都只收到了部分消息,并且 mosquitto 日志中充斥着“来自 xxx 的新连接”消息的垃圾邮件。优选地,第二订户将被拒绝以立即使这种错误显而易见。

为 Solace找到了一个类似的问题,它似乎提供了用新订阅者替换旧订阅者或拒绝新订阅者的选项。

但是,在检查mosquitto.conf的可用选项时,我看不到类似的选项。

mqtt mosquitto

1
推荐指数
1
解决办法
1647
查看次数