0

I'm making a python script for a twitch bot which basically acts as a slot machine. Disclaimer- I'm totally new to python, so please don't kill me.

At the start of the script, I have this code to check if the correct command was typed, check if the first argument is an integer, and check if the user has enough points. The idea is to let them choose an amount to gamble, so the cost line will be changed once i get it working.

if data.IsChatMessage():
    if (data.GetParam(0).lower() == settings["command"]
                    and isinstance((int(data.GetParam(1).lower())), int)
                    and settings["costs"] <= Parent.GetPoints(data.User)):

The input from the chat is always in a string form, even if it's only a number. I'm able to convert that to an int with int(), but if there's nothing or if there's something there other than numbers it crashes the script entirely. How can I keep the script from crashing and instead alert the user they need to input an integer? Thanks!

4
  • 1
    Can you explain in words why you think isinstance((int(data.GetParam(1).lower())), int) would work? Commented Sep 27, 2017 at 18:57
  • What exactly do you mean by crash? Do you get an exception? What is it? Commented Sep 27, 2017 at 18:58
  • 2
    Wrap the integer conversion code in a try ... except block, and catch the ValueError exception that occurs if the string does not represent a valid integer. See here. Commented Sep 27, 2017 at 18:59
  • 1
    Welcome to SO: you may want to read How to Ask and minimal reproducible example. As for your question, you may want to read on exception use in Python (e.g., www.pythonforbeginners.com/error-handling/exception-handling-in-python). Commented Sep 29, 2017 at 14:03

5 Answers 5

2

After doing a bit of research I think you can use a try/except block to make sure the value given by the user is actually a number.

try:
    i = int(string)
    # normal execution
except ValueError:
    # error msg

I got the answer here: Converting String to Int using try/except in Python

Sign up to request clarification or add additional context in comments.

Comments

2

You write:

isinstance(
    (int(data.GetParam(1).lower())),
    int
)

There are two problems with this fragment:

  • you call the int(..) constructor, and that can fail (error) if you provide it a non-integer (like "foobar18"); and
  • in case the constructor succeeds, then it is guaranteed that the outcome is an int, so the check is useless.

So now the question is what to do. We can construct an advanced check to inspect if a string is indeed an integer, but the problem is that we have to cover multiple cases, and it is easy to forget one.

Python is a language with the idea: EAFP: Easier to Ask for Forgiveness than Permission. It means that the philosophy of Python is to encourage trying something, and in exceptional cases, handle it, than first check if something is an integer.

So wen can write it as:

if data.IsChatMessage():
    try:
        int(data.GetParam(1).lower())  # we try it
        isint = True  # it worked!
    except ValueError:
        # that did not worked out very well, did it?
        isint = False
    if (data.GetParam(0).lower() == settings["command"]
                    and isint
                    and settings["costs"] <= Parent.GetPoints(data.User):
        pass

You better always specify the error you expect to see (ValueError) since if for instance data.GetParam(1) raises another error, you do not per se want to handle it there: it does not mean that data.GetParam(1).lower() is not an integer, it means that data.GetParam(1) has made some (other) error.

Comments

2

The line isinstance((int(data.GetParam(1).lower())), int) will raise a ValueError exception if data.GetParam(1) is not an integer.

As user8153 suggested, wrap the conversion with try, except block:

try:
    int(data.GetParam(1))
    print(data.GetParam(1) + 'is an integer')
except ValueError:
    print(data.GetParam(1) + 'is not an integer')

Alternatively, you may use data.GetParam(1).isdigit()

Comments

1

To check if a string can be casted to an int, simply use:

mystr = 'xx12'
if mystr.isnumeric():
    print('YES!')
else:
    print('NO')

1 Comment

That might not work well with Unicode. Documentation states that "Numeric characters include digit characters, and all characters that have the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH". int(u"\u2155") throws an exception.
0

You can use python built-in string's method .isnumeric() like this:

>>> "".isnumeric()
False
>>> "a".isnumeric()
False
>>> "5".isnumeric()
True
>>> "55".isnumeric()
True
>>> "55a".isnumeric()
False

but there might be a problem if you also want to check if the number is negative because:

>>> "-5".isnumeric()
False
>>> a = "-4"
>>> a.lstrip("-").isnumeric() and (len(a)-len(a.lstrip("-")) <= 1)
True
>>> a = "--4"
>>> a.lstrip("-").isnumeric() and (len(a)-len(a.lstrip("-")) <= 1)
False

The send part (len(a)-len(a.lstrip("-")) <= 1) checks if there is more than 1 "-"s before the number.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.