索引超出范围,同一行有多个列表



给定

>>> foo = [1, 1]
>>> bar = [1, 1, 1]
>>> print(foo[5], bar[5])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

如何判断哪个列表引发了异常?

对于更多非琐碎的例子来说,这是非常令人恼火的。有人能解释一下Python解释器是如何工作的,以至于它记不住它所在的字符吗?这似乎是一个太明显的设计错误,所以一定有原因,对吧?

JonSG的答案适用于所有版本的Python。然而,在未来,Python 3.11+将在其字节码中存储列偏移量。回溯将在出错的表达式下面加下划线:
Traceback (most recent call last):
File "C:UsersusernameDocumentsmodule.py", line 3, in <module>
print(foo[5], bar[5])
~~~^^^
IndexError: list index out of range

这要归功于在Python 3.11中实现的PEP 657,目前处于alpha版本,并将于2022年10月发布。

请注意,这个功能附带的内存成本很小,作者已经承认了这一点,他们说:

我们知道,某些用户可能无法接受此信息的额外成本,因此我们提出了一种选择退出机制,该机制将导致生成的代码对象没有额外信息,同时也允许pyc文件不包含额外信息。

可以通过将-Xno_debug_ranges传递给python来选择退出此功能。

简单的答案是,您可以通过将打印语句拆分为多行来强制执行(尽管我同意这更多的是一种变通方法,而不是真正的解决方案):

foo = [1, 1]
bar = [2, 2]
print(
foo[5],
bar[5]
)

应该会产生这样的结果:

Traceback (most recent call last):
File "test.py", line 4, in <module>
foo[5],
IndexError: list index out of range

同样需要注意的是,如果想要实际检查字节码以查看发生了什么,dis模块可能会在这里有所帮助:

import dis
code_block ='''
foo = [1, 1]
bar = [2, 2]
print(foo[5], bar[5])
'''
print(dis.dis(compile(code_block, "", "exec")))

告诉我:

2           0 LOAD_CONST               0 (1)
2 LOAD_CONST               0 (1)
4 BUILD_LIST               2
6 STORE_NAME               0 (foo)
3           8 LOAD_CONST               1 (2)
10 LOAD_CONST               1 (2)
12 BUILD_LIST               2
14 STORE_NAME               1 (bar)
4          16 LOAD_NAME                2 (print)
18 LOAD_NAME                0 (foo)
20 LOAD_CONST               2 (5)
22 BINARY_SUBSCR
24 LOAD_NAME                1 (bar)
26 LOAD_CONST               2 (5)
28 BINARY_SUBSCR
30 CALL_FUNCTION            2
32 POP_TOP
34 LOAD_CONST               3 (None)
36 RETURN_VALUE
None

因此,在我的平台上,foo[5]在bar之前进行评估(通过BINARY_SUBSCR.)。

I在返回时使用反编译编写了替换,以显示回溯中的位置。请参见loctraceback。它没有得到太多关注,我已经有一段时间没有尝试使用它了。

trepan3k调试器还使用反编译来更准确地显示停止时的位置。

2018年,我就这里使用的技术做了一次简短的演讲。有趣的是,当我举这样的例子时,例如。https://rocky.github.io/pycon2018.co/#/2.我在问题中得到的一个评论是,你为什么需要这样的东西。

如今,我倾向于只根据自己的个人需求、兴趣和时间来改进事情,而不太担心别人。(毕竟,开源工作应该意味着其他人也可以做出贡献。)

最新更新