Question

How to Check if a String Is a Number in Python

pythoncastingfloating-pointtype-conversioninteger

Question

How can I check whether a string represents a numeric value in Python?

For example, consider this function:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

This works, but it feels a little clunky. Is there a better or more Pythonic way to determine whether a string represents an integer or floating-point number?

Also, if the value comes from user input, it is still a string even if it looks like a number. In that case, how should I validate it before converting it?

Short Answer

By the end of this page, you will understand how Python checks whether a string can be treated as a number, why try/except is a common solution, when float() is appropriate, and what edge cases to watch for when validating user input.

Concept

In Python, a value read from input, a file, or an API often arrives as a string. Even if it looks like 42 or 3.14, Python still treats it as text until you convert it.

The key idea is:

  • A string represents a number if Python can successfully convert it to a numeric type.
  • A common way to test this is to attempt the conversion and handle failure.

For example:

float("3.14")   # works
float("42")     # works
float("hello")  # raises ValueError

This is why try/except is the standard Python approach. It follows a common Python style called EAFP: Easier to Ask Forgiveness than Permission. Instead of checking every possible format yourself, you try the operation and catch the error if it fails.

Why this matters:

  • User input must be validated before calculations.
  • Data from CSV files or APIs may contain invalid values.
  • Manual checks with string methods often miss important cases like negative numbers, decimals, or scientific notation.

For example, these are all valid for float():

"10"
"-3"
"4.5"
"1e6"
"  7.2  "

So although the try/except version may look simple, it is often the most reliable and Pythonic solution.

Mental Model

Think of float() like a number scanner at a gate.

  • If the string is in a format Python recognizes as numeric, it gets through.
  • If not, the scanner rejects it with an error.

Your job is not to inspect every character by hand unless you have special rules. Instead, you let Python's built-in converter do the checking.

Another way to think about it:

  • The string is a label on a box.
  • float() opens the box and checks whether the contents can be treated as a number.
  • If the box contains non-numeric text, conversion fails.

This is usually better than asking, "Does every character look numeric?" because real numeric formats can include:

  • a minus sign: -5
  • a decimal point: 3.14
  • exponent notation: 1e9
  • surrounding whitespace: 42
Take Quiz

Syntax and Examples

The most common pattern is:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

Example usage

print(is_number("10"))      # True
print(is_number("3.14"))    # True
print(is_number("-8"))      # True
print(is_number("1e3"))     # True
print(is_number("hello"))   # False
print(is_number("12a"))     # False

If you want the converted number too

Often, you do not just want to check the value. You want to convert it safely.

def parse_number(s):
    try:
        return float(s)
    except ValueError:
        return None

value = parse_number("4.25")
if value is not None:
    print("Valid number:", value)
else:
    print("Invalid number")

Checking specifically for integers

If you only want whole numbers:

def is_int_string(s):
    try:
        int(s)
        return True
    except ValueError:
        return False
print(is_int_string("42"))    # True
print(is_int_string("3.14"))  # False
print(is_int_string("-7"))    # True

Why not use str.isdigit()?

print("123".isdigit())   # True
print("-123".isdigit())  # False
print("3.14".isdigit())  # False

isdigit() only checks whether all characters are digit characters. It does not handle many valid numeric formats, so it is usually the wrong tool for general number validation.

Step by Step Execution

Consider this function:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

Now trace what happens with this input:

result = is_number("12.5")
print(result)

Step by step

  1. is_number("12.5") is called.
  2. Inside the try block, Python runs float("12.5").
  3. The conversion succeeds, producing 12.5 as a float.
  4. No exception happens, so the function returns True.
  5. print(result) displays True.

Now try invalid input:

result = is_number("12.5abc")
print(result)

Step by step

  1. is_number("12.5abc") is called.
  2. Python attempts float("12.5abc").
  3. The string is not a valid float format.
  4. Python raises a ValueError.
  5. Execution jumps to the except ValueError: block.
  6. The function returns False.
  7. print(result) displays False.

Small trace table

Inputfloat(input)Result
"25"succeedsTrue
"-8.2"succeedsTrue
"abc"raises ValueErrorFalse
"7x"raises ValueErrorFalse

Real World Use Cases

Checking numeric strings is common in real programs.

User input validation

age_text = input("Enter your age: ")

try:
    age = int(age_text)
    print("Age accepted:", age)
except ValueError:
    print("Please enter a whole number.")

Reading CSV or text files

Some columns may contain numbers stored as text.

values = ["10", "20.5", "N/A", "15"]

numbers = []
for item in values:
    try:
        numbers.append(float(item))
    except ValueError:
        pass

print(numbers)

Validating API data

An API might send prices as strings:

price_text = "19.99"

try:
    price = float(price_text)
    print(price * 2)
except ValueError:
    print("Invalid price format")

Filtering mixed data

items = ["12", "apple", "4.5", "-3", "hello"]

valid_numbers = []
for item in items:
    try:
        valid_numbers.append(float(item))
    except ValueError:
        continue

print(valid_numbers)
Take Quiz

Real Codebase Usage

In real projects, developers usually do more than return True or False. They often combine validation with conversion.

Pattern: validate by converting

def parse_price(text):
    try:
        return float(text)
    except ValueError:
        return None

This avoids converting twice.

Pattern: guard clause

def apply_discount(price_text):
    try:
        price = float(price_text)
    except ValueError:
        return "Invalid price"

    return price * 0.9

The invalid case is handled early, so the rest of the function stays simple.

Pattern: input loop

while True:
    text = input("Enter a number: ")
    try:
        value = float(text)
        break
    except ValueError:
        print("That was not a valid number. Try again.")

print("You entered:", value)

Pattern: strict business rules after conversion

A string may be numeric but still invalid for your program.

def parse_quantity(text):
    try:
        value = int(text)
    except ValueError:
        return None

    if value < 0:
        return None

    return value

Here, the value must be:

  • an integer
  • not negative

So validation often happens in two stages:

  1. Can it be converted?
  2. Does it meet business rules?

Common Mistakes

1. Using isdigit() for floats or negative numbers

Broken example:

"-3.5".isdigit()

This returns False, even though -3.5 is a valid number.

Avoid this by using float() or int() in a try block.

2. Checking before converting, then converting again

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

text = "4.2"
if is_number(text):
    value = float(text)

This converts the same value twice. In real code, it is often better to convert once and keep the result.

Better:

def parse_number(s):
    try:
        return float(s)
    except ValueError:
        return None

3. Forgetting that input() always returns a string

Broken thinking:

age = input("Age: ")
print(age + 1)

This fails because age is a string.

Correct:

age = int(input("Age: "))
print(age + 1)

4. Catching the wrong exception type

If you pass None to float(), Python raises TypeError, not ValueError.

float(None)

If your function may receive non-string values, handle that carefully.

def is_number(value):
    try:
        float(value)
        return True
    except (ValueError, TypeError):
        return False

5. Assuming every valid float string is useful

These are accepted by float():

float("nan")
float("inf")

If your program should reject these, add extra checks.

import math


def is_finite_number(s):
    try:
        value = float(s)
        return math.isfinite(value)
    except ValueError:
        return False

Comparisons

ApproachWorks for intsWorks for floatsWorks for negativesWorks for scientific notationBest use
str.isdigit()YesNoNoNoOnly simple digit-only strings
int(s) in try/exceptYesNoYesNoStrict integer validation
float(s) in try/exceptYesYesYesYesGeneral numeric string validation
Regular expressionDepends on patternDepends on patternDepends on patternDepends on patternCustom format rules

int() vs float()

  • Use int() if only whole numbers are valid.
  • Use float() if decimals should also be accepted.

try/except vs regex

  • try/except is simpler and uses Python's own parsing rules.
  • Regex is useful only when you need very specific formatting rules.

For most beginners and most real programs, try/except with float() or int() is the best choice.

Take Quiz

Cheat Sheet

# General number check
try:
    value = float(s)
except ValueError:
    # not numeric
# Integer-only check
try:
    value = int(s)
except ValueError:
    # not an integer

Quick rules

  • input() always returns a string.
  • float(s) accepts:
    • "10"
    • "-3.5"
    • "1e6"
    • " 42 "
  • int(s) accepts whole numbers only.
  • str.isdigit() is not a general number check.
  • If you need to reject nan or inf, use math.isfinite().

Useful helper

import math


def parse_finite_float(s):
    try:
        value = float(s)
        return value if math.isfinite(value) else None
    except ValueError:
        return None

Common edge cases

Inputint()float()
"5"validvalid
"-5"validvalid
"3.14"invalidvalid
"1e3"invalidvalid
"abc"invalidinvalid
"nan"invalidvalid
"inf"invalidvalid

FAQ

Is try/except the Pythonic way to check numeric strings?

Yes. In Python, attempting the conversion and catching errors is a common and recommended pattern.

Should I use isdigit() to check if a string is a number?

Usually no. isdigit() does not handle negative numbers, decimals, or scientific notation.

How do I check if a string is specifically an integer in Python?

Use int() inside a try/except ValueError block.

How do I check if user input is a valid float?

Use float() in a try block. If it raises ValueError, the input is not a valid float.

Does float() accept strings with spaces?

Yes. Surrounding whitespace is allowed, so float(" 3.5 ") works.

Can float() accept values like nan and inf?

Yes. If you want to reject them, check the result with math.isfinite().

Is it better to validate first and convert later?

Usually no. In many cases, it is cleaner to validate by converting once and then use the converted value.

Take Quiz

Mini Project

Description

Build a small input validator that repeatedly asks the user for a numeric value and rejects invalid entries. This demonstrates safe conversion, error handling, and the difference between accepting any float and accepting only finite numbers.

Goal

Create a program that keeps asking for a number until the user enters a valid finite float.

Requirements

Requirement 1 Requirement 2 Requirement 3

Take Quiz

Keep learning

Related questions

View more