Python: How to generate a random phone number?
Asked Answered
R

3

6

Not a duplicate of Making random phone number xxx-xxx-xxxx

My project uses python-phonenumbers and django-phonenumber-field for phone number validation. Within the project are vast lists of custom validation rules, for which naive approach like this will not be sufficient:

>>> import functools
>>> import random
>>> a = functools.partial(random.randint, 0, 9)
>>> gen = lambda: "+{}-{}{}{}-{}{}{}-{}{}{}{}".format(a(), a(), a(), a(), a(), a(), a(), a(), a(), a(), a())
>>> gen()
'+2-758-702-0180'  # Obviously wrong
>>> gen()
'+1-911-555-0180'  # Obviously wrong, it has 911 in it

So, without resorting to a brute-force while loop that has no upper bound, and without introducing an upper bound for such trivial problems, what better ways are there to generate valid phone numbers accepted by the validator itself?

from phonenumber_field.validators import validate_international_phonenumber
from django.core.exceptions import ValidationError

def generate_valid_number():
    while True:  # While loops are not desired, even with an upper bound!
        try:
            number = gen()
            validate_international_phonenumber(number)
            return number
        except ValidationError:
            pass
Ravishing answered 7/4, 2016 at 14:41 Comment(2)
related: Falsehoods Programmers Believe About Phone NumbersIrkutsk
@PeterWood this is for tests. Somewhat falsy is fine.Ravishing
C
7

I think the answer that davidn gave to this question should work especially since you're already using python-phonenumbers

I would recommend to use the phonenumbers package which is a python port of Google's libphonenumber which includes a data set of mobile carriers now:

import phonenumbers 
from phonenumbers import carrier
from phonenumbers.phonenumberutil import number_type

number = "+49 176 1234 5678"
carrier._is_mobile(number_type(phonenumbers.parse(number))) 

This will return True in case number is a mobile number or False otherwise. Note that the number must be a valid international number or an exception will be thrown. You can also use phonenumbers to parse phonenumber given a region hint.

Conciliar answered 7/4, 2016 at 15:3 Comment(0)
D
10

If you're using the package faker you can write a custom provider that can be re-used across your project.

import phonenumbers
from faker.providers.phone_number.en_US import Provider

class CustomPhoneProvider(Provider):
    def phone_number(self):
        while True:
            phone_number = self.numerify(self.random_element(self.formats))
            parsed_number = phonenumbers.parse(phone_number, 'US')
            if phonenumbers.is_valid_number(parsed_number):
                return phonenumbers.format_number(
                    parsed_number,
                    phonenumbers.PhoneNumberFormat.E164
                )

Used with factory_boy:

import factory
from faker import Faker

from .models import User
from .providers import CustomPhoneProvider

fake = Faker()
fake.add_provider(CustomPhoneProvider)

class UserFactory(factory.DjangoModelFactory):
    class Meta:
        model = User

    first_name = factory.Faker('first_name')
    last_name = factory.Faker('last_name')
    phone_number = factory.LazyAttribute(lambda _: fake.phone_number())
Dominions answered 10/9, 2019 at 17:47 Comment(1)
The code example with faker helped me validate my randomly generated phone number in my api automated test suite. Thanks @bdoubleMoratorium
C
7

I think the answer that davidn gave to this question should work especially since you're already using python-phonenumbers

I would recommend to use the phonenumbers package which is a python port of Google's libphonenumber which includes a data set of mobile carriers now:

import phonenumbers 
from phonenumbers import carrier
from phonenumbers.phonenumberutil import number_type

number = "+49 176 1234 5678"
carrier._is_mobile(number_type(phonenumbers.parse(number))) 

This will return True in case number is a mobile number or False otherwise. Note that the number must be a valid international number or an exception will be thrown. You can also use phonenumbers to parse phonenumber given a region hint.

Conciliar answered 7/4, 2016 at 15:3 Comment(0)
S
1

How to generate valid formatted phone number like: '+622183501XX', using google lib

from phonenumbers import PhoneNumberFormat, format_number
from faker import Faker

def generate_number():
    country_code = Faker().country_code()

    sample_number_obj = phonenumbers.example_number_for_type(country_code, PhoneNumberType.MOBILE)
    national_number_length = len(national_significant_number(sample_number_obj))

    number_obj = phonenumbers.parse(str(Faker().random_number(national_number_length)), country_code)
    number = phonenumbers.format_number(number_obj, phonenumbers.PhoneNumberFormat.E164)
    return number
Sura answered 17/1, 2024 at 10:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.