0

I am fairly new to Python and stuck on what seems like a simple problem. After months of waiting, I figured I would give in and write my own bot to get my kids a PS5. but I am running into stack depth issues.

The program just looks to see if an item is available and if not if refreshed the page and tries again. But I am throwing an exception after 1000 calls. I have looked for a way to clear the stack in Python but have not found anything.

I have also tried to restart the program when the stack > 1000 with os. execv(). But this is throwing an Exec format error.

Below is a truncated version with all the login and setup stuff removed. Thank you in advance for any help!

def click_and_buy():
    try:
        print('trying to buy')
        buy_now = driver.find_element_by_xpath('//*[@id="buy-now-button"]')
        buy_now.click()
    except Exception as e:
        print(len(inspect.stack(0)))
        if len(inspect.stack(0)) < 5:
            click_and_buy()
            time.sleep(1)
        else:
            restart()


def restart():
    # os.system('ps5_bots.py')
    os.execv(__file__, sys.argv)


if __name__ == '__main__':
    click_and_buy()
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 4
    Why don't you make it iterative, instead of recursive? – jonrsharpe May 02 '21 at 22:05
  • 2
    This would be trivial to convert too. Just remove the recursive call, wrap the `try` in a `while True`, and add a `break` after the call to `click`. – Carcigenicate May 02 '21 at 22:08
  • 1
    Does this answer your question? [Does Python optimize tail recursion?](https://stackoverflow.com/questions/13591970/does-python-optimize-tail-recursion) TLDR what you're asking is not possible, but you can use an iterative approach instead. – wjandrea May 02 '21 at 22:10
  • 2
    Just use a while loop. Python doesn't do tail call optimization. BTW you are a cool dad! – juanpa.arrivillaga May 03 '21 at 00:15

1 Answers1

3

Recursion is not a good fit for infinite repetitions. This is an x y problem.

Instead make the method iterative by using a while loop. Alternatively wrap the method with another that would invoke the loop:

def click_and_buy():
    print('trying to buy')
    buy_now = driver.find_element_by_xpath('//*[@id="buy-now-button"]')
    buy_now.click()


def click_and_buy_repeated():
    while True:
        click_and_buy()


if __name__ == '__main__':
    click_and_buy_repeated()
flakes
  • 21,558
  • 8
  • 41
  • 88
  • . . . wouldn't this continue forever and buy as many PS5s as possible? – Matt Blaha May 02 '21 at 22:40
  • 1
    Sure, you'll need to provide a way to exit the loop. You could have `click_and_buy` return a bool if it was successful or not, and then break the while loop depending on the value. – flakes May 02 '21 at 22:42