首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python脚本在不同的行处停止,不抛出任何异常。

Python脚本在不同的行处停止,不抛出任何异常。
EN

Stack Overflow用户
提问于 2019-02-07 11:15:34
回答 2查看 11.1K关注 0票数 5

我有一个Python,它对Word .docx文件进行了很大的解析工作(它已经处理了所有以前的文件)。它突然停止工作中期运行,没有抛出任何例外。整个代码包装在一个try-除-子句中,基本上如下所示:

代码语言:javascript
复制
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任务管理器,因此不能保证在脚本停止之前内存不会瞬间激增)

我已经重新运行了该脚本数百次,除了两次使用此错误之外,从未收到任何错误消息:

代码语言:javascript
复制
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 --看起来好像我的代码花费了大量的时间来评估正则表达式。基本上,这样的线条在观察跟踪时是很常见的:

代码语言:javascript
复制
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期间停止了,特别是在循环的第三次迭代中:

代码语言:javascript
复制
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模块中是否存在可能导致这种情况的缓存?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-25 15:34:56

这个问题最终得到了解决。最后,我使用来自:我如何知道我的python脚本挂在哪里?的提示调试了该程序

代码语言:javascript
复制
python -m trace --trace YOURSCRIPT.py

通过使用跟踪模块,我可以找到脚本停止运行的位置。在我的例子中,我运行了一个循环,每次迭代都会执行一组正则表达式检查。在这些检查过程中,脚本被窃听了,但每次都在不同的地方。我不完全确定,但是灾难性回溯是一个可能的原因,正如Mihai的回答所暗示的那样。可以肯定的是,我运行的正则表达式检查效率很低。我重写了脚本的整个regex部分,现在它运行良好。

因此,总括而言,我的问题的答案是:

  1. trace模块调试脚本,找出它的停止位置。这将我引向(2)
  2. 确保避免灾难性的回溯(以及正则表达式中可能的内存泄漏)

如果有人对Python错误没有错误消息的原因有更深入的解释,或者可以确认正则表达式中的内存泄漏会导致这种情况,请添加到我的答案中!

票数 8
EN

Stack Overflow用户

发布于 2019-02-07 13:20:01

您可以使用调试器运行它,并在挂起时暂停执行。看到堆栈跟踪。linux上的strace之类的工具也可能有所帮助。您的进程可能在某些io上被阻塞,或者它被某些死锁所困。

一个用户友好的调试器是在吡咯烷酮。将ipynb导出到一个普通的python文件。

从问题中编辑新信息

不要建造如此庞大的,不可预测的大政方针。只需检查一个循环中的所有模式。

您可能已经构建了一个易于使用灾难性回溯的正则表达式。

乍一看,我似乎并不是这样,但这需要再看一眼。

代码语言:javascript
复制
p = r"^([-+][ \t]*)?(([1-9][0-9]{0,2}( [0-9]{3})*((((,[0-9]*))|(,-)))?)|((([0-9]*(,[0-9]+)?)|([0-9]+((((,[0-9]*))|(,-)))?))))$"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54572087

复制
相关文章

相似问题

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