Chris Calo
Chris Calo

Reputation: 7838

Is there a built-in or more Pythonic way to try to parse a string to an integer

I had to write the following function to fail gracefully when trying to parse a string to an integer. I would imagine Python has something built in to do this, but I can't find it. If not, is there a more Pythonic way of doing this that doesn't require a separate function?

def try_parse_int(s, base=10, val=None):
  try:
    return int(s, base)
  except ValueError:
    return val

The solution I ended up using was a modification of @sharjeel's answer. The following is functionally identical, but, I think, more readable.

def ignore_exception(exception=Exception, default_val=None):
  """Returns a decorator that ignores an exception raised by the function it
  decorates.

  Using it as a decorator:

    @ignore_exception(ValueError)
    def my_function():
      pass

  Using it as a function wrapper:

    int_try_parse = ignore_exception(ValueError)(int)
  """
  def decorator(function):
    def wrapper(*args, **kwargs):
      try:
        return function(*args, **kwargs)
      except exception:
        return default_val
    return wrapper
  return decorator

Upvotes: 107

Views: 90245

Answers (12)

Lars Blumberg
Lars Blumberg

Reputation: 21441

Actually there is a "built-in", single line solution that doesn't require introducing a helper function:

>>> s = "123"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
123

>>> s = "abc"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None

>>> s = ""
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None

>>> s = "1a"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None

In case you need to support negative numbers, too, the following extension considers one (or more) leading dashes/minus as the algebraic sign for negative numbers:

>>> s = "-123"
>>> i = int(s) if s.split("-", 1)[-1].isdecimal() else None
>>> print(i)
-123

See also:

Upvotes: 57

T.M.
T.M.

Reputation: 629

PHP has a smart flexible integer casting algorithm.

Here is a similar attempt in Python.

def parseInt(txt: str) -> int:
    """
    PHP like integer parsing.

    Args:
        txt (str): string to parse.

    Returns:
        int: found integer.

    :Example:
    >>> parseInt("")
    0
    >>> parseInt("-")
    0
    >>> parseInt("-a")
    0
    >>> parseInt("-456as")
    -456
    >>> parseInt("123456z654")
    123456
    """
    if not len(txt):
        return 0
    result = ""
    if txt[0] == "-":
        result = "-0"
        txt = txt[1:]
    for char in txt:
        if char.isdigit():
            result += char
        else:
            break
    else:
        return 0
    return int(result)

Upvotes: 0

chava
chava

Reputation: 389

Depending on the circumstances, the following might fit the needs of some readers: leveraging short-circuiting, you can obtain either False or an actual integer, and you can check for its type.

pos = s.strip().lstrip("-")
number = pos.isdecimal() and pos.isdigit() and int(s)
if number is not False:

Just remember that False == 0 yields True. So, don't straight up compare it to an integer without first checking that is not False. Another option would be as follows,

pos = s.strip().lstrip("-") 
if pos.isdecimal() and pos.isdigit() and (int(s) == test_number):

Upvotes: 0

Deepak Verma
Deepak Verma

Reputation: 617

This could be another alternative for parsing string to int

while True:
try:
    n = input("Please enter an integer: ")
    n = int(n)
    break
except ValueError:
    print("No valid integer! Please try again ...")
print("Great, you successfully entered an integer!")

Upvotes: 1

sharjeel
sharjeel

Reputation: 6015

This is a pretty regular scenario so I've written an "ignore_exception" decorator that works for all kinds of functions which throw exceptions instead of failing gracefully:

def ignore_exception(IgnoreException=Exception,DefaultVal=None):
    """ Decorator for ignoring exception from a function
    e.g.   @ignore_exception(DivideByZero)
    e.g.2. ignore_exception(DivideByZero)(Divide)(2/0)
    """
    def dec(function):
        def _dec(*args, **kwargs):
            try:
                return function(*args, **kwargs)
            except IgnoreException:
                return DefaultVal
        return _dec
    return dec

Usage in your case:

sint = ignore_exception(ValueError)(int)
print sint("Hello World") # prints none
print sint("1340") # prints 1340

Upvotes: 61

Mack
Mack

Reputation: 31

myList = ['12', '13', '5', 'hope', 'despair', '69','0', '1.2']

myInts = [int(x) for x in myList if x.isdigit()]

Upvotes: 2

user2151391
user2151391

Reputation: 3

def parseint(string):
    result = '0'
    for x in string:
        if x.isdigit():
        result+=x
    else:
        return int(result)
    return int(result)

Upvotes: -3

Lukas Šalkauskas
Lukas Šalkauskas

Reputation: 14361

def intTryParse(value):
    try:
        return int(value), True
    except ValueError:
        return value, False

Upvotes: 48

abyx
abyx

Reputation: 72978

That's the pythonic way. In python, it's customary to use EAFP style - Easier to Ask Forgiveness than Permission.
That means you'd try first, and then clean up the mess if necessary.

Upvotes: 26

Roger Pate
Roger Pate

Reputation:

int() is the built-in and pythonic way, just like you have there.

It's usually easier and more common to use it directly though:

def show_square(user_input):
  """Example of using int()."""
  try:
    num = int(user_input, 10)
  except ValueError:
    print "Error" # handle not-an-integer case
    # or you may just want to raise an exception here
    # or re-raise the ValueError
  else:
    print "Times two is", num * 2

def another_example(user_input):
  try:
    num = int(user_input, 10)
  except ValueError:
    num = default
  print "Times two is", num * 2

Upvotes: 2

Macarse
Macarse

Reputation: 93173

I would go for:

def parse_int(s, base=10, val=None):
 if s.isdigit():
  return int(s, base)
 else:
  return val

But it's more or less the same thing.

Upvotes: 16

u0b34a0f6ae
u0b34a0f6ae

Reputation: 49833

No, it is already perfect. The val parameter could be better named default, though.

Documented in the official docs simply as int(x) -- x converted to integer

Upvotes: 7

Related Questions