Convert Figma logo to code with AI

daviddrysdale logopython-phonenumbers

Python port of Google's libphonenumber

3,481
412
3,481
10

Top Related Projects

Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers.

GoLang port of Google's libphonenumber library

PHP version of Google's phone number handling library

A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript

A JavaScript plugin for entering and validating international telephone numbers. Now includes React and Vue components.

Quick Overview

The python-phonenumbers library is a Python port of Google's libphonenumber library. It provides functionality for parsing, formatting, and validating international phone numbers. This library is particularly useful for applications that deal with phone numbers from various countries and need to handle them consistently.

Pros

  • Comprehensive support for international phone numbers
  • Regular updates to keep pace with changes in global phone number formats
  • Provides additional features like time zone lookup based on phone numbers
  • Well-documented and easy to use

Cons

  • Large library size due to extensive metadata for all countries
  • May be overkill for applications that only deal with phone numbers from a single country
  • Occasional discrepancies with the original Java implementation
  • Performance can be slower compared to simpler, country-specific solutions

Code Examples

Parsing a phone number:

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(number)

Formatting a phone number:

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.NATIONAL))
print(phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL))

Validating a phone number:

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(phonenumbers.is_valid_number(number))

Getting the time zone for a phone number:

import phonenumbers
from phonenumbers import timezone

number = phonenumbers.parse("+12125552368", None)
print(timezone.time_zones_for_number(number))

Getting Started

To get started with python-phonenumbers, follow these steps:

  1. Install the library using pip:

    pip install phonenumbers
    
  2. Import the library in your Python script:

    import phonenumbers
    
  3. Parse a phone number:

    number = phonenumbers.parse("+442083661177", None)
    
  4. Use the various functions provided by the library to manipulate and validate the phone number as needed.

For more detailed usage instructions and advanced features, refer to the project's documentation on GitHub.

Competitor Comparisons

Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers.

Pros of libphonenumber

  • Written in C++, offering potentially better performance for high-volume applications
  • Supports a wider range of programming languages through various ports
  • More frequent updates and contributions from a larger community

Cons of libphonenumber

  • More complex setup and integration, especially for Python projects
  • Larger codebase and dependencies, which may increase project size
  • Steeper learning curve for developers not familiar with C++

Code Comparison

python-phonenumbers:

import phonenumbers

number = phonenumbers.parse("+1 650 253 0000", None)
print(phonenumbers.is_valid_number(number))

libphonenumber (Java port):

import com.google.i18n.phonenumbers.*;

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
PhoneNumber number = phoneUtil.parse("+1 650 253 0000", null);
System.out.println(phoneUtil.isValidNumber(number));

Both libraries offer similar functionality, but python-phonenumbers provides a more Pythonic interface, while libphonenumber requires additional setup and language-specific bindings for non-C++ projects.

GoLang port of Google's libphonenumber library

Pros of phonenumbers

  • Faster performance due to optimizations and Cython implementation
  • Smaller package size, resulting in quicker installation and reduced dependencies
  • More frequent updates and active maintenance

Cons of phonenumbers

  • Less comprehensive documentation compared to python-phonenumbers
  • May have slightly fewer features or edge case handling capabilities
  • Potential compatibility issues with code relying on python-phonenumbers specifics

Code Comparison

python-phonenumbers:

import phonenumbers

number = phonenumbers.parse("+1 650 253 0000", None)
print(phonenumbers.is_valid_number(number))

phonenumbers:

from phonenumbers import parse, is_valid_number

number = parse("+1 650 253 0000", None)
print(is_valid_number(number))

Both libraries offer similar APIs, but phonenumbers may provide slight performance improvements due to its optimized implementation. The usage patterns are nearly identical, making it relatively easy to switch between the two libraries if needed. However, users should be aware of potential minor differences in behavior or available features when migrating from one library to the other.

PHP version of Google's phone number handling library

Pros of libphonenumber-for-php

  • Written in PHP, making it easier to integrate into PHP projects
  • Regularly updated to match the latest Google's libphonenumber data
  • Supports Composer for easy installation and dependency management

Cons of libphonenumber-for-php

  • May have slightly slower performance compared to the Python version
  • Potentially larger memory footprint due to PHP's nature
  • Less extensive documentation compared to the Python counterpart

Code Comparison

python-phonenumbers:

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(phonenumbers.is_valid_number(number))

libphonenumber-for-php:

use libphonenumber\PhoneNumberUtil;

$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse("+442083661177", "GB");
echo $phoneUtil->isValidNumber($number);

Both libraries offer similar functionality, but with syntax differences specific to their respective languages. The PHP version requires explicit instantiation of the PhoneNumberUtil class, while the Python version uses module-level functions.

A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript

Pros of libphonenumber-js

  • Written in JavaScript, making it ideal for web and Node.js applications
  • Smaller package size, resulting in faster load times and reduced bundle size
  • Supports both CommonJS and ES6 module systems

Cons of libphonenumber-js

  • Less comprehensive coverage of phone number formats compared to python-phonenumbers
  • May have fewer advanced features for phone number parsing and validation
  • Potentially less frequent updates to country-specific phone number data

Code Comparison

python-phonenumbers:

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(phonenumbers.is_valid_number(number))
print(phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL))

libphonenumber-js:

import { parsePhoneNumber } from 'libphonenumber-js'

const number = parsePhoneNumber('+442083661177')
console.log(number.isValid())
console.log(number.format('INTERNATIONAL'))

Both libraries provide similar functionality for parsing and formatting phone numbers, but with syntax differences reflecting their respective programming languages. The python-phonenumbers library offers a more extensive API with additional features, while libphonenumber-js provides a more streamlined approach suitable for JavaScript environments.

A JavaScript plugin for entering and validating international telephone numbers. Now includes React and Vue components.

Pros of intl-tel-input

  • Client-side implementation, suitable for web applications
  • Provides a user-friendly interface with country flag selection
  • Offers real-time validation and formatting of phone numbers

Cons of intl-tel-input

  • Limited to JavaScript environments
  • Requires additional server-side validation for complete security
  • May have a larger footprint in terms of file size and load time

Code Comparison

intl-tel-input (JavaScript):

$("#phone").intlTelInput({
  utilsScript: "path/to/utils.js",
  nationalMode: true,
  formatOnDisplay: true
});

python-phonenumbers (Python):

import phonenumbers

number = phonenumbers.parse("+442083661177", None)
print(phonenumbers.is_valid_number(number))

Summary

intl-tel-input is ideal for web-based applications requiring a user-friendly interface for phone number input. It offers real-time validation and formatting but is limited to client-side use. python-phonenumbers, on the other hand, is a server-side solution that provides robust parsing and validation capabilities across various programming environments. The choice between the two depends on the specific requirements of the project, such as the need for a graphical interface versus backend processing.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

phonenumbers Python Library

Coverage Status

This is a Python port of Google's libphonenumber library It supports Python 2.5-2.7 and Python 3.x (in the same codebase, with no 2to3 conversion needed).

Original Java code is Copyright (C) 2009-2015 The Libphonenumber Authors.

Release HISTORY, derived from upstream release notes.

Documentation

Installation

Install using pip with:

pip install phonenumbers

Example Usage

The main object that the library deals with is a PhoneNumber object. You can create this from a string representing a phone number using the parse function, but you also need to specify the country that the phone number is being dialled from (unless the number is in E.164 format, which is globally unique).

>>> import phonenumbers
>>> x = phonenumbers.parse("+442083661177", None)
>>> print(x)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> type(x)
<class 'phonenumbers.phonenumber.PhoneNumber'>
>>> y = phonenumbers.parse("020 8366 1177", "GB")
>>> print(y)
Country Code: 44 National Number: 2083661177 Leading Zero: False
>>> x == y
True
>>> z = phonenumbers.parse("00 1 650 253 2222", "GB")  # as dialled from GB, not a GB number
>>> print(z)
Country Code: 1 National Number: 6502532222 Leading Zero(s): False

The PhoneNumber object that parse produces typically still needs to be validated, to check whether it's a possible number (e.g. it has the right number of digits) or a valid number (e.g. it's in an assigned exchange).

>>> z = phonenumbers.parse("+120012301", None)
>>> print(z)
Country Code: 1 National Number: 20012301 Leading Zero: False
>>> phonenumbers.is_possible_number(z)  # too few digits for USA
False
>>> phonenumbers.is_valid_number(z)
False
>>> z = phonenumbers.parse("+12001230101", None)
>>> print(z)
Country Code: 1 National Number: 2001230101 Leading Zero: False
>>> phonenumbers.is_possible_number(z)
True
>>> phonenumbers.is_valid_number(z)  # NPA 200 not used
False

The parse function will also fail completely (with a NumberParseException) on inputs that cannot be uniquely parsed, or that can't possibly be phone numbers.

>>> z = phonenumbers.parse("02081234567", None)  # no region, no + => unparseable
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2350, in parse
    "Missing or invalid default region.")
phonenumbers.phonenumberutil.NumberParseException: (0) Missing or invalid default region.
>>> z = phonenumbers.parse("gibberish", None)
Traceback (most recent call last):
  File "phonenumbers/phonenumberutil.py", line 2344, in parse
    "The string supplied did not seem to be a phone number.")
phonenumbers.phonenumberutil.NumberParseException: (1) The string supplied did not seem to be a phone number.

Once you've got a phone number, a common task is to format it in a standardized format. There are a few formats available (under PhoneNumberFormat), and the format_number function does the formatting.

>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.NATIONAL)
'020 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
'+44 20 8366 1177'
>>> phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164)
'+442083661177'

If your application has a UI that allows the user to type in a phone number, it's nice to get the formatting applied as the user types. The AsYouTypeFormatter object allows this.

>>> formatter = phonenumbers.AsYouTypeFormatter("US")
>>> formatter.input_digit("6")
'6'
>>> formatter.input_digit("5")
'65'
>>> formatter.input_digit("0")
'650'
>>> formatter.input_digit("2")
'650 2'
>>> formatter.input_digit("5")
'650 25'
>>> formatter.input_digit("3")
'650 253'
>>> formatter.input_digit("2")
'650-2532'
>>> formatter.input_digit("2")
'(650) 253-22'
>>> formatter.input_digit("2")
'(650) 253-222'
>>> formatter.input_digit("2")
'(650) 253-2222'

Sometimes, you've got a larger block of text that may or may not have some phone numbers inside it. For this, the PhoneNumberMatcher object provides the relevant functionality; you can iterate over it to retrieve a sequence of PhoneNumberMatch objects. Each of these match objects holds a PhoneNumber object together with information about where the match occurred in the original string.

>>> text = "Call me at 510-748-8230 if it's before 9:30, or on 703-4800500 after 10am."
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(match)
...
PhoneNumberMatch [11,23) 510-748-8230
PhoneNumberMatch [51,62) 703-4800500
>>> for match in phonenumbers.PhoneNumberMatcher(text, "US"):
...     print(phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164))
...
+15107488230
+17034800500

You might want to get some information about the location that corresponds to a phone number. The geocoder.description_for_number does this, when possible.

>>> from phonenumbers import geocoder
>>> ch_number = phonenumbers.parse("0431234567", "CH")
>>> geocoder.description_for_number(ch_number, "de")
'Zürich'
>>> geocoder.description_for_number(ch_number, "en")
'Zurich'
>>> geocoder.description_for_number(ch_number, "fr")
'Zurich'
>>> geocoder.description_for_number(ch_number, "it")
'Zurigo'

For mobile numbers in some countries, you can also find out information about which carrier originally owned a phone number.

>>> from phonenumbers import carrier
>>> ro_number = phonenumbers.parse("+40721234567", "RO")
>>> carrier.name_for_number(ro_number, "en")
'Vodafone'

You might also be able to retrieve a list of time zone names that the number potentially belongs to.

>>> from phonenumbers import timezone
>>> gb_number = phonenumbers.parse("+447986123456", "GB")
>>> timezone.time_zones_for_number(gb_number)
('Atlantic/Reykjavik', 'Europe/London')

For more information about the other functionality available from the library, look in the unit tests or in the original libphonenumber project.

Memory Usage

The library includes a lot of metadata, potentially giving a significant memory overhead. There are two mechanisms for dealing with this.

  • The normal metadata (just over 2 MiB of generated Python code) for the core functionality of the library is loaded on-demand, on a region-by-region basis (i.e. the metadata for a region is only loaded on the first time it is needed).
  • Metadata for extended functionality is held in separate packages, which therefore need to be explicitly loaded separately. This affects:
    • The geocoding metadata (~19 MiB), which is held in phonenumbers.geocoder and used by the geocoding functions (geocoder.description_for_number, geocoder.description_for_valid_number or geocoder.country_name_for_number).
    • The carrier metadata (~1 MiB), which is held in phonenumbers.carrier and used by the mapping functions (carrier.name_for_number or carrier.name_for_valid_number).
    • The timezone metadata (~100 KiB), which is held in phonenumbers.timezone and used by the timezone functions (time_zones_for_number or time_zones_for_geographical_number).

The phonenumberslite version of the library does not include the geocoder, carrier and timezone packages, which can be useful if you have problems installing the main phonenumbers library due to space/memory limitations.

If you need to ensure that the metadata memory use is accounted for at start of day (i.e. that a subsequent on-demand load of metadata will not cause a pause or memory exhaustion):

  • Force-load the normal metadata by calling phonenumbers.PhoneMetadata.load_all().
  • Force-load the extended metadata by importing the appropriate packages (phonenumbers.geocoder, phonenumbers.carrier, phonenumbers.timezone).

Static Typing

The library includes a set of type stub files to support static type checking by library users. These stub files signal the types that should be used, and may also be of use in IDEs which have integrated type checking functionalities.

These files are written for Python 3, and as such type checking the library with these stubs on Python 2.5-2.7 is unsupported.

Project Layout

  • The python/ directory holds the Python code.
  • The resources/ directory is a copy of the resources/ directory from libphonenumber. This is not needed to run the Python code, but is needed when upstream changes to the master metadata need to be incorporated.
  • The tools/ directory holds the tools that are used to process upstream changes to the master metadata.