我有一个Python,它对Word .docx文件进行了很大的解析工作(它已经处理了所有以前的文件)。它突然停止工作中期运行,没有抛出任何例外。整个代码包装在一个try-除-子句中,基本上如下所示:
try:
report.read_and_postprocess() #: My parsing process (with ALOT of code inside)
print("Finished...")
except NoObjectForElementError as error:
print("Known error")
raise error
except:
print("Other error")
raise
finally:
print("Write this!")为了定位错误,我尝试使用print()语句来隔离代码停止的位置。然而,当我接近时,停止点移动到另一个地方。
在我看来,这似乎是内存泄漏,或者是对我的Python环境的一些其他限制--但我并不擅长调试这个环境。我查看了我的脚本的内存和CPU使用情况。在脚本的末尾,它只消耗大约87 to的内存,使得计算机的总内存仅从67%移动到68%。(为此,我只查看Windows 10任务管理器,因此不能保证在脚本停止之前内存不会瞬间激增)
我已经重新运行了该脚本数百次,除了两次使用此错误之外,从未收到任何错误消息:
Python Fatal Error: GC Object already Tracked我不知道如何继续调试这个,有人有什么窍门吗?它可能是由记忆引起的,还是我怎样才能发现呢?还有其他Python限制会导致这种情况吗?(例如,我读过关于嵌套for -循环的20限制的文章,但对我来说不应该是这样的)
更新:在report.read_and_postprocess()行期间停止。
有关环境的信息: Windows 10、Anaconda 3、Python3.7。脚本在anaconda提示符中运行,激活了我的环境。
更新:--我发现了这个技巧:https://stackoverflow.com/a/3443779/6700475 --看起来好像我的代码花费了大量的时间来评估正则表达式。基本上,这样的线条在观察跟踪时是很常见的:
sre_compile.py(596): return isinstance(obj, (str, bytes))
sre_compile.py(763): pattern = p
sre_compile.py(764): p = sre_parse.parse(p, flags)
--- modulename: sre_parse, funcname: parse
sre_parse.py(922): source = Tokenizer(str)
--- modulename: sre_parse, funcname: __init__
sre_parse.py(225): self.istext = isinstance(string, str)
sre_parse.py(226): self.string = string
sre_parse.py(227): if not self.istext:
sre_parse.py(229): self.decoded_string = string
sre_parse.py(230): self.index = 0
sre_parse.py(231): self.next = None
sre_parse.py(232): self.__next()
--- modulename: sre_parse, funcname: __next
sre_parse.py(234): index = self.index
sre_parse.py(235): try:
sre_parse.py(236): char = self.decoded_string[index]
sre_parse.py(240): if char == "\\":
sre_parse.py(247): self.index = index + 1
sre_parse.py(248): self.next = char
sre_parse.py(924): if pattern is None:
sre_parse.py(925): pattern = Pattern()
--- modulename: sre_parse, funcname: __init__
sre_parse.py(77): self.flags = 0
sre_parse.py(78): self.groupdict = {}我运行了跟踪,并且(至少这次)它在re.match期间停止了,特别是在循环的第三次迭代中:
def is_numeric(text):
""" Return whether a trimmed string is numeric
Numeric formats:
1
1.2 (US style)
1,2 (EU style)
1,200,340 (US style)
1 200 340 (other style)
1.200.340 (eu style?)
1,200,340.67
1 200 340,67
1 200 340.67
1.200.340,67
-23
-23.98
-2 454 981.21
+ 24
- 24
+ 24.9183
12321
543525,-
123123,
12389.
12 489.
12 432,
"""
if len(text) == 0:
return False
#: Try float
try:
float(text)
except ValueError:
pass
except:
raise
else:
return True
#: look for all characters that should not be in a number
if not re.match(r"^[-+0-9., ]*$", text):
return False
#: Verify numeric format
#: 1.200.200,78
#: 1,200,200.78
#: 1 200 200,78
#: 1 200 200.78
#: 1200200,78
#: 1200200.78
#: - 1200200.78
#: + 1.200.200,78
#: 1200200,-
#: -1 200 200,-
#: etc.
variants = ((r",", r"\."),
(r"\.", r","),
(r" ", r","),
(r" ", r"\."))
for (tho, dec) in variants:
dec_exp_opt = r"(%s[0-9]*)" % dec
if dec == ",":
dec_exp_opt = r"((%s)|(,-))" % dec_exp_opt
threesep = r"[1-9][0-9]{0,2}(%s[0-9]{3})*(%s)?" % (tho, dec_exp_opt)
nullsep = r"(([0-9]*(%s[0-9]+)?)|([0-9]+(%s)?))" % (dec, dec_exp_opt)
expr = r"^([-+][ \t]*)?((%s)|(%s))$" % (threesep, nullsep)
test = re.match(expr, text) #: IT HAS STOPPED HERE IN ITERATION 3!!
if test:
return True
return False它现在试图解决的表达式可能(也可能不是)是随机的:^([-+][ \t]*)?(([1-9][0-9]{0,2}( [0-9]{3})*((((,[0-9]*))|(,-)))?)|((([0-9]*(,[0-9]+)?)|([0-9]+((((,[0-9]*))|(,-)))?))))$表示值2017-05-29 (最好返回2017-05-29)。
(可怜的)有道理吗?正则表达式可以导致脚本停止而不会引发异常?re模块中是否存在可能导致这种情况的缓存?
发布于 2019-02-25 15:34:56
这个问题最终得到了解决。最后,我使用来自:我如何知道我的python脚本挂在哪里?的提示调试了该程序
python -m trace --trace YOURSCRIPT.py通过使用跟踪模块,我可以找到脚本停止运行的位置。在我的例子中,我运行了一个循环,每次迭代都会执行一组正则表达式检查。在这些检查过程中,脚本被窃听了,但每次都在不同的地方。我不完全确定,但是灾难性回溯是一个可能的原因,正如Mihai的回答所暗示的那样。可以肯定的是,我运行的正则表达式检查效率很低。我重写了脚本的整个regex部分,现在它运行良好。
因此,总括而言,我的问题的答案是:
trace模块调试脚本,找出它的停止位置。这将我引向(2)如果有人对Python错误没有错误消息的原因有更深入的解释,或者可以确认正则表达式中的内存泄漏会导致这种情况,请添加到我的答案中!
发布于 2019-02-07 13:20:01
您可以使用调试器运行它,并在挂起时暂停执行。看到堆栈跟踪。linux上的strace之类的工具也可能有所帮助。您的进程可能在某些io上被阻塞,或者它被某些死锁所困。
一个用户友好的调试器是在吡咯烷酮。将ipynb导出到一个普通的python文件。
从问题中编辑新信息
不要建造如此庞大的,不可预测的大政方针。只需检查一个循环中的所有模式。
您可能已经构建了一个易于使用灾难性回溯的正则表达式。
乍一看,我似乎并不是这样,但这需要再看一眼。
p = r"^([-+][ \t]*)?(([1-9][0-9]{0,2}( [0-9]{3})*((((,[0-9]*))|(,-)))?)|((([0-9]*(,[0-9]+)?)|([0-9]+((((,[0-9]*))|(,-)))?))))$"https://stackoverflow.com/questions/54572087
复制相似问题