python
strings
integer
type-checking
programming

How can I check if a string represents an int, without using try/except?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python offers several ways to check if a string represents an integer without try/except: str.isdigit() for non-negative integers, str.lstrip('+-').isdigit() for signed integers, and re.fullmatch() for full regex validation. While try/except with int() is the most Pythonic (EAFP) approach, there are valid reasons to avoid it — performance in tight loops, avoiding exception-driven control flow, or pre-validating user input before processing. This article covers all non-exception approaches.

Method 1: str.isdigit()

python
1# Works for non-negative integers only
2"123".isdigit()    # True
3"0".isdigit()      # True
4"".isdigit()       # False
5"-5".isdigit()     # False (minus sign is not a digit)
6"3.14".isdigit()   # False (decimal point is not a digit)
7"12 ".isdigit()    # False (trailing space)

isdigit() returns True only if all characters are digits and the string is non-empty. It does not handle negative numbers, leading + signs, or whitespace.

Method 2: Handle Signed Integers

python
1def is_integer(s):
2    s = s.strip()  # Remove leading/trailing whitespace
3    if not s:
4        return False
5    if s[0] in ('+', '-'):
6        return s[1:].isdigit()
7    return s.isdigit()
8
9# Tests
10print(is_integer("123"))    # True
11print(is_integer("-42"))    # True
12print(is_integer("+7"))     # True
13print(is_integer("  99 ")) # True
14print(is_integer(""))       # False
15print(is_integer("-"))      # False
16print(is_integer("3.14"))   # False

Strip whitespace first, then check if the first character is a sign. After removing the optional sign, verify the rest contains only digits.

Method 3: Regular Expression

python
1import re
2
3def is_integer(s):
4    return bool(re.fullmatch(r'[+-]?\d+', s.strip()))
5
6# Tests
7print(is_integer("123"))     # True
8print(is_integer("-42"))     # True
9print(is_integer("+0"))      # True
10print(is_integer(""))        # False
11print(is_integer("12.3"))    # False
12print(is_integer("0xFF"))    # False
13
14# Pre-compile for performance in loops
15INT_PATTERN = re.compile(r'[+-]?\d+')
16
17def is_integer_fast(s):
18    return bool(INT_PATTERN.fullmatch(s.strip()))

re.fullmatch() validates the entire string against the pattern. Pre-compile the regex with re.compile() when checking many strings.

Method 4: str.isnumeric() and str.isdecimal()

python
1# isnumeric() — includes Unicode numeric characters (fractions, superscripts)
2"123".isnumeric()      # True
3"½".isnumeric()        # True (fraction)
4"²".isnumeric()        # True (superscript)
5"-5".isnumeric()       # False
6
7# isdecimal() — strictest, only 0-9 and Unicode decimals
8"123".isdecimal()      # True
9"½".isdecimal()        # False
10"٣".isdecimal()        # True (Arabic-Indic digit)
11
12# isdigit() — between isdecimal and isnumeric
13"²".isdigit()          # True (superscript)
14"½".isdigit()          # False
15
16# For plain integer validation, isdecimal() is usually the safest choice
17def is_plain_integer(s):
18    s = s.strip()
19    if s and s[0] in ('+', '-'):
20        s = s[1:]
21    return s.isdecimal() and len(s) > 0

isdecimal() is the strictest — it only matches characters that represent decimal digits. isdigit() also matches superscripts. isnumeric() is the broadest, matching fractions and Roman numerals in Unicode.

Method 5: Custom Character Check

python
1def is_integer(s):
2    s = s.strip()
3    if not s:
4        return False
5    start = 1 if s[0] in '+-' else 0
6    if start >= len(s):
7        return False
8    return all(c in '0123456789' for c in s[start:])
9
10# Or using ASCII values
11def is_integer_ascii(s):
12    s = s.strip()
13    if not s:
14        return False
15    start = 1 if s[0] in '+-' else 0
16    if start >= len(s):
17        return False
18    return all(48 <= ord(c) <= 57 for c in s[start:])

Performance Comparison

python
1import timeit
2
3s = "123456789"
4
5# Fastest for simple cases
6timeit.timeit(lambda: s.isdigit(), number=1_000_000)         # ~0.07s
7
8# Slightly slower with sign handling
9timeit.timeit(lambda: s.lstrip('+-').isdigit(), number=1_000_000)  # ~0.12s
10
11# Regex (pre-compiled) is competitive
12pattern = re.compile(r'[+-]?\d+')
13timeit.timeit(lambda: pattern.fullmatch(s), number=1_000_000)  # ~0.20s
14
15# try/except is fast when it succeeds, slow when it fails
16timeit.timeit(lambda: int(s), number=1_000_000)               # ~0.15s (success)

str.isdigit() is the fastest for simple non-negative checks. For mixed valid/invalid data, string methods outperform try/except because exception handling has overhead on failure.

Common Pitfalls

  • isdigit() returns True for Unicode superscripts: "²".isdigit() returns True, but int("²") raises ValueError. Use isdecimal() for strict ASCII digit validation.
  • Empty string returns False but bare sign doesn't: Both "".isdigit() and "-".lstrip('-').isdigit() return False, but you should explicitly handle these edge cases for clarity.
  • Leading/trailing whitespace: " 42 ".isdigit() returns False because spaces are not digits. Always call .strip() first if your input might contain whitespace.
  • No support for other integer formats: None of these methods handle hex (0xFF), octal (0o77), or binary (0b1010). Use regex or a custom parser for these.
  • Forgetting that int() accepts more than digits: int(" -42 ") works fine with whitespace and signs. The string-method approach requires you to handle these manually, which adds complexity.

Summary

  • str.isdigit() — fast check for non-negative integers (digits only)
  • str.lstrip('+-').isdigit() — quick signed integer check
  • re.fullmatch(r'[+-]?\d+', s) — regex for complete validation
  • str.isdecimal() — strictest string method (no Unicode superscripts)
  • Always .strip() input before checking to handle whitespace
  • Pre-compile regex patterns when validating many strings in a loop

Course illustration
Course illustration

All Rights Reserved.