Fatal python error cannot recover from stack overflow python runtime state initialized

Created on 2020-11-30 06:01 by xxm, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Created on 2020-11-30 06:01 by xxm, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg382111 — (view) Author: Xinmeng Xia (xxm) Date: 2020-11-30 06:01
The following program 1 can crash in Python 3. We have reproduce it in the Python version 3.5, 3.6, 3.7, 3.8, 3.9, 3.10. This bug seems to be similar to issue 36272, however, the tracking system shows issue 36272 has been fixed and the program 2, which triggers issue 36272, will not cause crash (“core dump”) in Python 3.8, 3.9, 3.10.
We have attached the stack trace in the end of this report.

Program 1: 
========================
import logging

def rec():
	try:
		logging.error("foo")
	except:
		pass
	rec()
rec()
========================

Program 2: 
========================
import logging

def rec():
	logging.error("foo")
	rec()
rec()
======================
The error message is like following:
“
ERROR:root:foo
ERROR:root:foo
ERROR:root:foo
ERROR:root:foo
…
ERROR:root:foo
ERROR:root:foo
ERROR:root:foo
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized

Current thread 0x00007f0fa440b700 (most recent call first):
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 420 in usesTime
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 643 in usesTime
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 675 in format
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 938 in format
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1094 in emit
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 963 in handle
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1673 in callHandlers
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1611 in handle
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1601 in _log
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 1483 in error
  File "/usr/local/python310/lib/python3.10/logging/__init__.py", line 2080 in error
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 8 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
….
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  File "/home/xxm/Desktop/methodfuzzer/error/loggingtest.py", line 12 in rec
  ...
Aborted (core dumped)”
msg382112 — (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2020-11-30 06:51
This might be the expected behavior. See https://bugs.python.org/issue25222

If you already caught a RecursionError and you keep recursing anyway, once you go 50 levels beyond sys.getrecursionlimit(), the interpreter crashes regardless of what is `except`ed. In /Python/ceval.c, there's this:

    if (tstate->overflowed) {
        if (tstate->recursion_depth > recursion_limit + 50) {
            /* Overflowing while handling an overflow. Give up. */
            Py_FatalError("Cannot recover from stack overflow.");
        }
        return 0;
    }

In your Program 2, when the interpreter raises a `RecursionError`, it is raised normally and everything is fine.

In your Program 1, when the interpreter raises a `RecursionError`, it is `except`ed, so the interpreter thinks it's okay to keep going, and when it does, it raises more `RecursionError`s, which it keeps `except`ing, until it finally can't go any farther ( > 50 + sys.getrecursionlimit()), and has no option but to crash.

"Cannot recover from stack overflow." seems to make sense to me: when the interpreter tries to recover, the code won't let it.
msg382114 — (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2020-11-30 08:10
See also #42500
msg382117 — (view) Author: Xinmeng Xia (xxm) Date: 2020-11-30 08:19
But program like following program 3 will not cause any core dump, RecursionError is also being caught in this  Recursion.
program 3
def rec():
	try:
		rec()
	except:
		pass
rec()

Beside,I use sys.setrecursionlimit(80), and the program 1 still cause core dump.I print sys.getrecursionlimit(),the value is 1000. 80 is << 50 +1000, it shouldn't cause core dump.
msg382128 — (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2020-11-30 09:04
sys.getrecursionlimit() returns whatever was passed to the most recent call of sys.setrecursionlimit(...), with some system default (here 1000).

Catching a RecursionError might be fine sometimes, but the issue is that Program 1 catches a RecursionError *and then keeps recursing more* rather than stopping.

I think it might have to be the responsibility of the Python user to make sure that if a RecursionError is to be caught, that the program can recover without making things much worse. It's my understanding that the extra buffer of +50 is to make sure that the programmer has room to stop the overflow and do any necessary cleanup [1].

If no attempt is made to clean up, then it seems reasonable to me that Python should crash, unless there's some idea of what could happen that I'm missing. The interpreter could allow arbitrary recursion during the cleanup until the C stack overflows, but that sort of defeats the point of the recursion checker. It could raise some new ExtraSuperRecurionError, but that doesn't fix anything: what if *that* error is caught ;) ?

[1] to get back to a recursion depth lower than some lower threshold: https://github.com/python/cpython/blob/master/Include/internal/pycore_ceval.h#L98
msg382151 — (view) Author: Mark Shannon (Mark.Shannon) * (Python committer) Date: 2020-11-30 14:24
Duplicate of 42500
History
Date User Action Args
2022-04-11 14:59:38 admin set github: 86675
2020-11-30 14:24:29 Mark.Shannon set status: open -> closed

nosy:
+ Mark.Shannon
messages:
+ msg382151

resolution: duplicate
stage: resolved

2020-11-30 09:04:41 Dennis Sweeney set messages:
+ msg382128
2020-11-30 08:19:09 xxm set messages:
+ msg382117
2020-11-30 08:10:55 ronaldoussoren set nosy:
+ ronaldoussoren
messages:
+ msg382114
2020-11-30 06:51:27 Dennis Sweeney set nosy:
+ Dennis Sweeney
messages:
+ msg382112
2020-11-30 06:01:25 xxm create

Error:

Fatal Python error: Cannot recover from stack overflow. Python runtime state: initialized Current thread 0x000019e8 (most recent call first): File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailutils.py", line 57 in _has_surrogates File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemail_policybase.py", line 287 in _sanitize_header File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemail_policybase.py", line 316 in header_fetch_parse File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailmessage.py", line 471 in get File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailmessage.py", line 578 in get_content_type File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailmessage.py", line 594 in get_content_maintype File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailfeedparser.py", line 295 in _parsegen File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailfeedparser.py", line 180 in _call_parse File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailfeedparser.py", line 176 in feed File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailparser.py", line 56 in parse File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libemailparser.py", line 67 in parsestr File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libhttpclient.py", line 221 in parse_headers File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libhttpclient.py", line 327 in begin File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libhttpclient.py", line 1322 in getresponse File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesurllib3connectionpool.py", line 416 in _make_request File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesurllib3connectionpool.py", line 665 in urlopen File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesurllib3poolmanager.py", line 330 in urlopen File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesurllib3request.py", line 171 in request_encode_body File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesurllib3request.py", line 79 in request File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesseleniumwebdriverremoteremote_connection.py", line 397 in _request File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesseleniumwebdriverremoteremote_connection.py", line 374 in execute File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesseleniumwebdriverremotewebdriver.py", line 319 in execute File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesseleniumwebdriverremotewebdriver.py", line 976 in find_element File "C:UsersJuliusAppDataLocalProgramsPythonPython38-32libsite-packagesseleniumwebdriverremotewebdriver.py", line 598 in find_element_by_css_selector File "C:UsersJuliusDesktoptestKlad2.py", line 51 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart File "C:UsersJuliusDesktoptestKlad2.py", line 58 in trycart

So I’ve created this piece of code where it monitors the website of https://www.Jdsports.nl. My script refreshes the website and checks if the sneakers are in stock, it repeats this for as long as possible. As I said, this script works perfectly until it has refreshed the site for about 1500 times (if my maths are correct :)). After 1500 times it gives the error above^^^^. I’m running my code with headless selenium. Does anyone know why I get that error??

Posts: 3,889

Threads: 56

Joined: Jan 2018

Reputation:
307

The error traceback shows a high level of recursion. Try to break the recursivity of the algorithm.

micseydel

Involuntary Spiderweb Collector

Administrators

Posts: 2,343

Threads: 61

Joined: Sep 2016

Reputation:
73

I suspect you want this (it’s probably not worth changing your algorithm). If you do need to change your algorithm, I suspect you’ll need to manage a stack manually.

Posts: 59

Threads: 26

Joined: Jan 2020

Reputation:
0

Feb-05-2020, 09:11 PM
(This post was last modified: Feb-05-2020, 09:13 PM by julio2000.)

(Feb-05-2020, 08:18 PM)micseydel Wrote: The error traceback shows a high level of recursion. Try to break the recursivity of the algorithm.

I tried to add the line:

sys.setrecursionlimit(10000)

But nothing really changed :O.


(Feb-05-2020, 07:52 PM)Gribouillis Wrote: The error traceback shows a high level of recursion. Try to break the recursivity of the algorithm.

I’m sorry I’m a little bit of a noob but I don’t understand what you mean and how to solve it oeps :O

Posts: 3,889

Threads: 56

Joined: Jan 2018

Reputation:
307

Feb-05-2020, 09:35 PM
(This post was last modified: Feb-05-2020, 09:43 PM by Gribouillis.)

julio2000 Wrote:My script refreshes the website and checks if the sneakers are in stock, it repeats this for as long as possible

This task does not normally need a high level of recursion. It means that you are repeating the task by the means of recursion instead of repeating it by an infinite loop. The structure of the program should be

while True:
    refresh_the_website()
    check_if_the_sneakers_are_in_stock()

None of these functions should call itself, directly or indirectly.

micseydel

Involuntary Spiderweb Collector

Administrators

Posts: 2,343

Threads: 61

Joined: Sep 2016

Reputation:
73

(Feb-05-2020, 09:35 PM)Gribouillis Wrote: The structure of the program should be

If they’re performing a depth-first search, then recursion is a very natural solution, and a simple loop won’t be enough without them managing a stack manually, which isn’t necessarily worth doing…

That said, it sounds like there’s no base-case. Usually for a recursive web crawler like this, you’d specify a max depth.

You should probably share your code if you expect more help.

Posts: 59

Threads: 26

Joined: Jan 2020

Reputation:
0

(Feb-05-2020, 09:35 PM)Gribouillis Wrote:

julio2000 Wrote:My script refreshes the website and checks if the sneakers are in stock, it repeats this for as long as possible

This task does not normally need a high level of recursion. It means that you are repeating the task by the means of recursion instead of repeating it by an infinite loop. The structure of the program should be

while True:
    refresh_the_website()
    check_if_the_sneakers_are_in_stock()

None of these functions should call itself, directly or indirectly.

and how do I say when it needs to be False?

Posts: 3,889

Threads: 56

Joined: Jan 2018

Reputation:
307

Feb-05-2020, 09:51 PM
(This post was last modified: Feb-05-2020, 09:56 PM by Gribouillis.)

As @micseydel said, we know too little to give a valuable help.

From the traceback, we can see that the error occured during the call of a function named find_element_by_css_selector(). Again I cannot imagine such a function involving a high level of recursion without an error in the logic of the program. Typically, a function with that name will traverse a document’s tree which depth is small.

Posts: 59

Threads: 26

Joined: Jan 2020

Reputation:
0

(Feb-05-2020, 09:51 PM)Gribouillis Wrote: As @micseydel said, we know too little to give a valuable help.

From the traceback, we can see that the error occured during the call of a function named find_element_by_css_selector(). Again I cannot imagine such a function involving a high level of recursion without an error in the logic of the program. Typically, a function with that name will traverse a document’s tree which depth is small.

my script is kind of as following:

def Trycart():
    try:
        check if it's instock
    except Exception:      <- when it's out of stock it will give an Exception
        Trycart            <- so when it's out of stock it will try this function again

It is a bit more complicated then this^^ but this kind of sums it up. So I’m not using a while loop but I’m constantly repeating the function. Could this b the problem?

Posts: 3,889

Threads: 56

Joined: Jan 2018

Reputation:
307

Feb-05-2020, 10:34 PM
(This post was last modified: Feb-05-2020, 10:35 PM by Gribouillis.)

Yes I do think it could be the problem. You could replace this for example with

while True:
    try:
        check if it's in stock
    except Exception:
        continue
    else:
        break

Issue

I imatates QT’s official documentation to write a calcuator example.

I try to rewrite the source code into python and make some changes. My code is as blow:

import sys

from PySide6.QtWidgets import (QApplication, QSizePolicy, QWidget, QToolButton, QGridLayout)
from PySide6 import QtCore


class Advanced_Calculator(QWidget):
    def __init__(self):
        super(Advanced_Calculator, self).__init__()

        self.mainwindow = QGridLayout(self)

        # Digit buttons and operator buttons

        self.widget_button = QWidget()

        self.button_digit = []

        for i in range(0, 10):
            self.button_digit.append(Button(str(i)))

        self.button_factor = Button("!")
        self.button_lbracket = Button("(")
        self.button_rbracket = Button(")")
        self.button_backspace = Button("<-")
        self.button_division = Button("/")
        self.button_log = Button("log")
        self.button_multiply = Button("X")
        self.button_sqrt = Button("√")
        self.button_minus = Button("-")
        self.button_power = Button("^")
        self.button_plus = Button("+")
        self.button_abs = Button("|x|")
        self.button_const = Button("Const")
        self.button_dot = Button(".")
        self.button_equal = Button("=")

        # Buttons layout with 0 spacing

        self.layout_button = QGridLayout()
        self.layout_button.setSpacing(0)

        self.layout_button.addWidget(self.button_factor, 0, 0, 1, 1)
        self.layout_button.addWidget(self.button_lbracket, 0, 1, 1, 1)
        self.layout_button.addWidget(self.button_rbracket, 0, 2, 1, 1)
        self.layout_button.addWidget(self.button_backspace, 0, 3, 1, 1)
        self.layout_button.addWidget(self.button_division, 0, 4, 1, 1)
        self.layout_button.addWidget(self.button_log, 1, 0, 1, 1)

        for i in range(1, 10):
            self.layout_button.addWidget(self.button_digit[i], 3 - ((i - 1) // 3), (i - 1) % 3 + 1, 1, 1)

        self.layout_button.addWidget(self.button_multiply, 1, 4, 1, 1)
        self.layout_button.addWidget(self.button_sqrt, 2, 0, 1, 1)
        self.layout_button.addWidget(self.button_minus, 2, 4, 1, 1)
        self.layout_button.addWidget(self.button_power, 3, 0, 1, 1)
        self.layout_button.addWidget(self.button_plus, 3, 4, 1, 1)
        self.layout_button.addWidget(self.button_power, 3, 0, 1, 1)
        self.layout_button.addWidget(self.button_power, 3, 0, 1, 1)
        self.layout_button.addWidget(self.button_power, 3, 0, 1, 1)
        self.layout_button.addWidget(self.button_power, 3, 0, 1, 1)
        self.layout_button.addWidget(self.button_abs, 4, 0, 1, 1)
        self.layout_button.addWidget(self.button_const, 4, 1, 1, 1)
        self.layout_button.addWidget(self.button_digit[0], 4, 2, 1, 1)
        self.layout_button.addWidget(self.button_dot, 4, 3, 1, 1)
        self.layout_button.addWidget(self.button_equal, 4, 4, 1, 1)

        self.widget_button.setLayout(self.layout_button)

        # button layout set to mainwindow

        self.mainwindow.addWidget(self.widget_button)


class Button(QToolButton):
    def __init__(self, text, parent=None):
        super(Button, self).__init__(parent)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.setText(text)

    def sizeHint(self) -> QtCore.QSize:
        size = self.sizeHint()
        size.setHeight(size.height + 20)
        size.setWidth(max(size.width(), size.height()))
        # size.rheight() += 20
        # size.rwidth() = max(size.width(), size.height())

        return size


if __name__ == "__main__":
    app = QApplication([])

    Calculator = Advanced_Calculator()
    Calculator.show()

    sys.exit(app.exec())

When I debug these code, the «Fatal Python error: Cannot recover from stack overflow» occurs. And now it is known to me that the error is caused by the sizeHint() function. Where is the problem?

By the way, the function was rewrite by me with my comprehending of the sizeHint() function. And the official documentation uses the two lines code blow which I made them comments, and it doesn’t work, too. Well, I also can’t figure out where is the problem.

Solution

Consider the code…

def sizeHint(self) -> QtCore.QSize:
    size = self.sizeHint()
    size.setHeight(size.height + 20)
    size.setWidth(max(size.width(), size.height()))
    # size.rheight() += 20
    # size.rwidth() = max(size.width(), size.height())

    return size

The line…

size = self.sizeHint()

causes Button::sizeHint to call itself leading to infinite recursion and, hence, a stack overflow. Perhaps you meant to call the base class implementation instead…

size = super(Button, self).sizeHint()

Answered By — G.M.

I’ve come to a dead end, and after excessive (and unsuccessful) Googling, I need help.

I’m building a simple PyQt4 Widget where it lies out a grid of 60×80 squares, each initialized to None. If the user clicks on that box it changes color based on how many times left-clicked, defined by this list:

self.COLORS=[
        (0, 0, 255),        #WATER
        (255, 210, 128),    #SAND
        (0, 128, 0),       #GREEN
        (255, 255, 0),    #YELLOW
        (255, 165, 0),    #ORANGE
        (255, 0, 0)          #RED

]

If the user right clicks, it flood fills an area, using the common recursive flood fill algo. This works perfectly for small spaces, however if the space is large enough the program fails with the error Fatal Python error: Cannot recover from . I have no idea how to fix this, perhaps a flood fill that isn’t recursive?

All squares and subsequent color codes are stored in self.cells so by setting self.cells[(y,x)]=1 would set cell (y,x) to the Sand color.

Here is the program in whole.

import sys
from PyQt4 import QtGui, QtCore

class Example(QtGui.QWidget):

    def __init__(self, cell_size=10, swidth=800, sheight=600):
        QtGui.QWidget.__init__(self)
        self.resize(swidth,sheight)

        self.cell_size = cell_size
        self.height = sheight
        self.width = swidth
        self.columns = self.width // self.cell_size
        self.rows = self.height // self.cell_size

        self.COLORS=[
                (0, 0, 255),        #WATER
                (255, 210, 128),    #SAND
                (0, 128, 0),       #GREEN
                (255, 255, 0),    #YELLOW
                (255, 165, 0),    #ORANGE
                (255, 0, 0)          #RED

        ]

        self.cells = {(x,y):None for x in range(1,self.columns+1) for y in range(1,self.rows+1)}        

    def translate(self,pixel_x, pixel_y):
        "Translate pixel coordinates (pixel_x,pixel_y), into grid coordinates"
        x = pixel_x * self.columns // self.width + 1
        y = pixel_y * self.rows // self.height  + 1
        return x,y

    def check_cell(self,x,y):
        if self.cells[(x,y)] <= 0:
            self.cells[(x,y)]=0
        elif self.cells[(x,y)] >= len(self.COLORS)-1:
            self.cells[(x,y)]=len(self.COLORS)-1
        else:
            pass

    def draw_cell(self, qp, col, row):
        x1,y1 = (col-1) * self.cell_size, (row-1) * self.cell_size
        x2,y2 = (col-1) * self.cell_size + self.cell_size, (row-1) * self.cell_size + self.cell_size 
        qp.drawRect(x1, y1, x2-x1, y2-y1)

    def color_cell(self, qp, col, row):
        qp.setBrush(QtGui.QColor(*self.COLORS[self.cells[(col,row)]]))
        self.draw_cell(qp, col, row)

    def draw_grid(self, qp):
        qp.setPen(QtGui.QColor(128,128,128)) # gray
        # Horizontal lines
        for i in range(self.rows):
            qp.drawLine(0, i * self.cell_size, self.width, i * self.cell_size)
        # Vertical lines
        for j in range(self.columns):
            qp.drawLine(j * self.cell_size, 0, j * self.cell_size, self.height)

    def set_all(self, type):
        self.cells = {(x,y):type for x in range(1,self.columns+1) for y in range(1,self.rows+1)}  
        self.repaint()

    def fill(self, x, y, type):
        print(x,y)
        if x < 1 or x >= self.columns+1 or y < 1 or y >= self.rows+1:
            return
        if self.cells[(x,y)] != None:
            return
        self.cells[(x,y)] = type
        self.repaint()
        self.fill(x+1, y, type)
        self.fill(x-1, y, type)
        self.fill(x, y+1, type)
        self.fill(x, y-1, type)


    def paintEvent(self, e):
        qp = QtGui.QPainter()
        qp.begin(self)
        self.draw_grid(qp)
        for row in range(1, self.rows+1):
            for col in range(1, self.columns+1):
                if self.cells[(col,row)] != None:
                    self.color_cell(qp, col, row)
        qp.end()

    def drawPoints(self, qp):
        size = self.size()

        for i in range(1000):
            x = random.randint(1, size.width()-1)
            y = random.randint(1, size.height()-1)
            qp.drawPoint(x, y)  

    def mousePressEvent(self, e):
        x,y = self.translate(e.pos().x(),e.pos().y())

        if e.button() == QtCore.Qt.LeftButton:
            if self.cells[(x,y)] == None:
                self.cells[(x,y)]=0
            else:
                self.cells[(x,y)]+=1
                self.check_cell(x,y)

        elif e.button() == QtCore.Qt.RightButton:
            self.fill(x,y,0)
            '''
            if self.cells[(x,y)] == None:
                self.cells[(x,y)]=0
            else:  
                self.cells[(x,y)]-=1
                self.check_cell(x,y)
            '''            
        else: pass

        self.repaint()

    def save(self):
        return self.cells

    def open(self, new_cells):
        self.cells=new_cells
        self.repaint()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Can anyone help diagnose the problem or perhaps point in a direction to fix it?

Avatar

I have created a custom module, made some changes, added a transient model and added a qweb report and when upgrading I cannot access odoo. It loads but when I load the web the service crashes. I get this error in the console:

If i create a new database, and re-install the module, everything works fine.

File "/usr/lib/python3.8/traceback.py", line 476 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 493 in __init__
File "/usr/lib/python3.8/traceback.py", line 120 in format_exception
File "/usr/lib/python3.8/traceback.py", line 167 in format_exc
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 136 in __init__
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 339 in _compiled_fn
File "<template>", line 1 in template_web_html_container_65
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_escandallo_resultado_comparar_59
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_report_assets_common_76
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 260 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 58 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 326 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-55>", line 2 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 296 in _get_asset_nodes
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-54>", line 2 in _get_asset_nodes
File "<template>", line 1 in template_web_report_layout_68
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_html_container_65
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_escandallo_resultado_comparar_59
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_report_assets_common_76
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 260 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 58 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 326 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-55>", line 2 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 296 in _get_asset_nodes
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-54>", line 2 in _get_asset_nodes
File "<template>", line 1 in template_web_report_layout_68
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_html_container_65
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_escandallo_resultado_comparar_59
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_report_assets_common_76
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 260 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 58 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 326 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-55>", line 2 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 296 in _get_asset_nodes
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-54>", line 2 in _get_asset_nodes
File "<template>", line 1 in template_web_report_layout_68
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_html_container_65
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_escandallo_resultado_comparar_59
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_report_assets_common_76
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 260 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 58 in render
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 326 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-55>", line 2 in _get_asset_content
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/ir_qweb.py", line 296 in _get_asset_nodes
File "/usr/lib/python3/dist-packages/odoo/tools/cache.py", line 90 in lookup
File "<decorator-gen-54>", line 2 in _get_asset_nodes
File "<template>", line 1 in template_web_report_layout_68
File "/usr/lib/python3/dist-packages/odoo/addons/base/models/qweb.py", line 332 in _compiled_fn
File "<template>", line 1 in template_web_html_container_65

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Fatal not a git repository or any of the parent directories git ошибка
  • Fatal ni connect error 12537
  • Fatal ni connect error 12170 oracle что это
  • Fatal metro exodus ошибка при запуске
  • Fatal metro exodus a crash has been detected by bugtrap как исправить ошибку

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии