Python 括號層數限制(SyntaxError: too many nested parentheses)
代碼
n = 201
s = '(' * n + ')' * n
print(eval(s))
錯誤信息
Traceback (most recent call last):
File "/mnt/hgfs/Python-3.9.1/test.py", line 7, in <module>
print(eval(s))
File "<string>", line 1
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
^
SyntaxError: too many nested parentheses
當 n <= 200
時,程序是正常的。
debug
在 Python 源碼目錄下,使用 find
指令尋找源碼中對應的錯誤信息:
$ find ./ -name "*.[ch]" | xargs grep "too many nested parentheses"
./Parser/tokenizer.c: return syntaxerror(tok, "too many nested parentheses");
在 ${Python-3.9.1}/Parser/tokenizer.h
中:
#define MAXLEVEL 200 /* Max parentheses level */
在 ${Python-3.9.1}/Parser/tokenizer.c
中可以看出,這個宏限制的不僅是小括號,中括號和大括號也是一起計算的。
/* Keep track of parentheses nesting level */
switch (c) {
case '(':
case '[':
case '{':
if (tok->level >= MAXLEVEL) {
return syntaxerror(tok, "too many nested parentheses");
}
tok->parenstack[tok->level] = c;
tok->parenlinenostack[tok->level] = tok->lineno;
tok->level++;
break;
case ')':
case ']':
case '}':
if (!tok->level) {
return syntaxerror(tok, "unmatched '%c'", c);
}
tok->level--;
int opening = tok->parenstack[tok->level];
...
把 MAXLEVEL
改為 300
,然后重新編譯 Python ,程序成功執行:
()
當 n
增大到 301
時,再次報錯 SyntaxError: too many nested parentheses
舊版 Python
MAXLEVEL
這個宏不是一直就有的,我記得它是在 3.8
的某個版本引入的,詳細信息參考 issue33306
我下載了 Python 3.7.9 ,這個版本在 n >= 94
時報錯:
s_push: parser stack overflow
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(eval(s))
MemoryError
尋找錯誤信息對應的源碼:
$ find ./ -name "*.[ch]" | xargs grep "parser stack overflow"
./Parser/parser.c: fprintf(stderr, "s_push: parser stack overflow\n");
然后在 ./Parser/parser.h
中找到 DFA 棧的大小:
#define MAXSTACK 1500
將這個值改為 3000 然后重新編譯,最大括號層數從 93 增長到了 187
問題
stackentry s_base[MAXSTACK];
里面都存了什么東西,為什么MAXSTACK
的值都上千了,最大括號層數還不是很多?- 為什么使用新的實現,按照 issue 33306 的說明,是為了實現更友好的錯誤提示,那么為什么這么改?新的數據結構把括號分離出去以后怎么做計算?
這些問題只有在仔細研究源碼以后才能了解,暫時擱置了,以后有時間再回來填上這個坑。