首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Python会引发异常,尽管只有一个例外块呢?

为什么Python会引发异常,尽管只有一个例外块呢?
EN

Stack Overflow用户
提问于 2020-01-22 09:12:44
回答 2查看 459关注 0票数 0

想象一下以下代码:

代码语言:javascript
复制
def query(sql, data):
    with conn as cursor:
        try:
            cursor.execute(sql, data)
            rows = cursor.fetchall()
            conn.commit()
        except Exception as e:
            print(cursor._last_executed)
            print(e)

调用它时,err.InterfaceError("(0, '')")将从最后一行print(e)中上升。

如果它是从print(cursor._last_executed)中崛起的,我甚至可以理解它,因为cursor可能是不可用的。但事实并非如此。

为什么,当我的异常应该处理所有事情的时候?

请不要去讨论简单的例外是好的还是坏的,这是另一个话题。问题是,在这种情况下,为什么会出现例外。

编辑:异常在很重的DB负载下很少出现。你将无法复制它。

Edit2:我成功地将跟踪复制为哨兵报告中的文本:

代码语言:javascript
复制
InterfaceError: (0, '')
  File "run_signal_generator.py", line 39, in <module>
    main()
  File "run_signal_generator.py", line 35, in main
    ds.run_trades_stream()
  File "/home/deribit/rubber-band/data_stream/data_streamer.py", line 223, in run_trades_stream
    self.process_data(data)
  File "/home/deribit/rubber-band/data_stream/data_streamer.py", line 97, in process_data
    self.start_new_candle(timeframe)
  File "/home/deribit/rubber-band/data_stream/data_streamer.py", line 117, in start_new_candle
    self.notify()
  File "/home/deribit/rubber-band/data_stream/observer.py", line 13, in notify
    observer.update()
  File "/home/deribit/rubber-band/data_stream/observer.py", line 26, in update
    self.process_data()
  File "/home/deribit/rubber-band/data_stream/signal_generator.py", line 131, in process_data
    return self.process_potential_new_trade()
  File "/home/deribit/rubber-band/data_stream/signal_generator.py", line 160, in process_potential_new_trade
    return self.process_enter_signal()
  File "/home/deribit/rubber-band/data_stream/signal_generator.py", line 407, in process_enter_signal
    trade_id = self.store_enter_signal_db(data)
  File "/home/deribit/rubber-band/data_stream/signal_generator.py", line 522, in store_enter_signal_db
    return query(sql, db_data)["id"]
  File "/home/deribit/rubber-band/helpers/mysql.py", line 19, in query
    print(e)
  File "pymysql/connections.py", line 881, in __exit__
    self.commit()
  File "pymysql/connections.py", line 798, in commit
    self._execute_command(COMMAND.COM_QUERY, "COMMIT")
  File "pymysql/connections.py", line 1122, in _execute_command
    raise err.InterfaceError("(0, '')")

实际上,它声称例外是从这条线上升的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-22 10:52:00

算出来了。

这就是正在发生的事情:

1)主query引发一个错误。

( 2)处理。

3)由于query位于上下文管理器中,上下文管理器将退出它的对象,例如连接实例。

4)由于MySQL服务器的消失,连接类的__exit__方法无法正确执行。

5)由于不能正确执行,它在上下文管理器的范围内,在query内部的裸处理异常范围之外,引发一个错误query

如果您使用以下代码进行实验,可以获得相同的结果:

代码语言:javascript
复制
class ContextManagerException(Exception):
    pass


class TryBlockException(Exception):
    pass


class A(object):
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, tb):
        raise ContextManagerException


with A() as a:
    try:
        raise TryBlockException
        pass
    except Exception as e:
        print(e)

如您所见,上升的异常确实是从上下文管理器上升的,实际上它是从print(e)行上升的,因为它是从上下文管理器执行的最后一行。

票数 1
EN

Stack Overflow用户

发布于 2020-01-22 09:20:00

看起来类似于this old question:mysql连接和游标并不是线程安全的,所以如果您在多个线程之间共享连接(而不是每个线程有一个连接),那么它们的状态基本上随时都会中断。

可能由于某种原因,MySQL上的__str__连接错误使服务器尝试获取更多信息,如果其他线程已经更改了连接状态,这些信息就会中断。cursor._last_executed可能没有这个问题,因为在执行请求或响应返回时只在本地保存信息。

正如其他评论者所指出的,如果您得到一个异常,请提供完整的跟踪和错误消息,而不是信息的一小部分。如果您需要匿名,部分追溯,但ESP或假设是必要的越少,越好。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59856128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档