0

I want to access the country name using a phone number with Python. But for some input data it does not return anything, how can I fix this? In the Phonenumbers documentation, I spotted the following suspicious comment:

If the number has already been found valid for one region, then we don't know which region it belongs to so we return nothing.

import phonenumbers
from phonenumbers import geocoder

phone = '+39391359045341'
p = phonenumbers.parse(phone)
geocoder.country_name_for_number(p, 'en')
xjcl
  • 12,848
  • 6
  • 67
  • 89
  • 3
    Please provide a test case and show what the actual (failing) result is and what the expected (good) result should be. – jarmod Feb 18 '22 at 11:51
  • Either do coding for that phonenumber library and improve its code so it can detect your region or create a new module for this task. – gajendragarg Feb 18 '22 at 12:04
  • OP's post clearly states the issue is that nothing is returned by the `country_name_for_number` function. The region is _Italy_, so it should obviously be in the library. – xjcl Feb 18 '22 at 12:15
  • Actually, it might be related to `+39` being both used by Italy and the Vatican. – xjcl Feb 18 '22 at 12:16

3 Answers3

2

The reason your code fails is that +39 is used by multiple countries (Italy and the Vatican), and as the comment you quoted explains, in that case the function just returns nothing because the region is ambiguous. (A few functions inside of the library seem to just use the major region though).

So here is my fixed function if you want the major region (returns "Italy"):

import phonenumbers.geocoder

def country_name_for_number(p: phonenumbers.PhoneNumber, lang="en") -> str:
    rc = phonenumbers.geocoder.region_code_for_country_code(p.country_code)
    return phonenumbers.geocoder._region_display_name(rc, lang)

Or if you want all regions (returns ["Italy", "Vatican"])

def country_names_for_number(p: phonenumbers.PhoneNumber, lang="en") -> list[str]:
    rcs = phonenumbers.geocoder.region_codes_for_country_code(p.country_code)
    return [phonenumbers.geocoder._region_display_name(rc, lang) for rc in rcs]

Original comment:

I was able to reproduce the issue of country_name_for_number not returning anything. I checked the source code and it internally calls region_code_for_country_code to look up the 2 letter code (+39... -> IT) and then uses a LOCALE_DATA dictionary inside of _region_display_name to look up the code (IT -> Italy). Interactively:

import phonenumbers.geocoder

c = phonenumbers.parse("+39391359045341")
print(phonenumbers.geocoder.country_name_for_number(c, "en"))  # returns 'None'?!
print(phonenumbers.geocoder.region_code_for_country_code(c.country_code))  # 'IT'
print(phonenumbers.geocoder._region_display_name("IT", "en"))  # Italy
xjcl
  • 12,848
  • 6
  • 67
  • 89
1

@xjcl answer makes perfect sense, I hadn't inspected the library and I used an incorrect method. Using the function provided by @xjcl

#check whether a phone number is valid or not
import phonenumbers
from phonenumbers import geocoder

people = ['John', 'Mary', 'Peter']
texts = ['+39391359045341', '+919876543210', '+559876543210']
# Parsing String to Phone number
numbers = [phonenumbers.parse(txt) for txt in texts]
valids = [phonenumbers.is_valid_number(number) for number in numbers]
countries = [country_names_for_number(number) for number in numbers]

result = []
for i in range(len(valids)):
    if valids[i]:
        result.append((people[i], texts[i], countries[i]))
print(result)

Original comment:

Apparently there are some bugs in the phonenumbers library, see, when running on some numbers it finds a country state (Maranhão) instead of the country itself (Brazil). Report to the library builder.

    #check whether a phone number is valid or not
    import phonenumbers
    people = ['John', 'Mary', 'Peter']
    texts = ['+39391359045341', '+919876543210', '+559876543210']
    # Parsing String to Phone number
    numbers = [phonenumbers.parse(txt) for txt in texts]
    valids = [phonenumbers.is_valid_number(number) for number in numbers]
    possibles = [phonenumbers.is_possible_number(number) for number in numbers]
    print(valids)
    print(possibles)

    #find carrier and region of a phone number
    from phonenumbers import geocoder, carrier
    carriers = [carrier.name_for_number(number, 'en') for number in numbers]
    regions = [geocoder.description_for_number(number, 'en') for number in numbers]

    result = []
    for i in range(len(valids)):
        if valids[i]:
            result.append((people[i], texts[i], carriers[i], regions[i]))
    print(result)
David
  • 67
  • 5
  • 1
    `description_for_number` is supposed to print a description (which could be a city or state), not necessarily the country. – xjcl Feb 18 '22 at 12:34
0
import phonenumbers.geocoder

c = phonenumbers.parse("+393891916627")
print(phonenumbers.geocoder.country_name_for_number(c, "en")) # THIS WILL RETURN NOTHING
print(phonenumbers.geocoder.region_code_for_country_code(c.country_code))  # 'IT'
print(phonenumbers.geocoder._region_display_name("IT", "en"))  #CHANGING IT TO ITS FULL NAME 
toyota Supra
  • 3,181
  • 4
  • 15
  • 19
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Diego Borba Aug 30 '23 at 12:25