I have multiple Network Interface Cards on my computer, each with its own IP address.
When I use gethostbyname(gethostname()) from Python's (built-in) socket module, it will only return one of them. How do I get the others?
I have multiple Network Interface Cards on my computer, each with its own IP address.
When I use gethostbyname(gethostname()) from Python's (built-in) socket module, it will only return one of them. How do I get the others?
Use the netifaces module. Because networking is complex, using netifaces can be a little tricky, but here's how to do what you want:
>>> import netifaces
>>> netifaces.interfaces()
['lo', 'eth0']
>>> netifaces.ifaddresses('eth0')
{17: [{'broadcast': 'ff:ff:ff:ff:ff:ff', 'addr': '00:11:2f:32:63:45'}], 2: [{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}], 10: [{'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::211:2fff:fe32:6345%eth0'}]}
>>> for interface in netifaces.interfaces():
... print netifaces.ifaddresses(interface)[netifaces.AF_INET]
...
[{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]
[{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}]
>>> for interface in netifaces.interfaces():
... for link in netifaces.ifaddresses(interface)[netifaces.AF_INET]:
... print link['addr']
...
127.0.0.1
10.0.0.2
This can be made a little more readable like this:
from netifaces import interfaces, ifaddresses, AF_INET
def ip4_addresses():
ip_list = []
for interface in interfaces():
for link in ifaddresses(interface)[AF_INET]:
ip_list.append(link['addr'])
return ip_list
If you want IPv6 addresses, use AF_INET6 instead of AF_INET. If you're wondering why netifaces uses lists and dictionaries all over the place, it's because a single computer can have multiple NICs, and each NIC can have multiple addresses, and each address has its own set of options.
As this thread indicates, there is a lot of ways to acchive the same result, my suggested way is to leverage the build-in family filter in getaddrinfo() and parse the standardised tuple like so:
from socket import getaddrinfo, AF_INET, gethostname
for ip in getaddrinfo(host=gethostname(), port=None, family=AF_INET):
print(ip[4][0])
Example output:
192.168.55.1
192.168.170.234
You should directly obtain all IP configured IP addresses, e.g. by running ifconfig and parsing its output (it's also possible to do what ifconfig does directly in Python, see how it is done in C). If you want host names, use gethostbyaddr.
It's linux only, but there's a very simple recipe here http://code.activestate.com/recipes/439094/
It probably uses similar code to the netifaces package mentioned in another answer (but current version linked here)
The socket.getaddrinfo() doesn't actually return the bound ip address for the device. If your hosts file contains a line with "127.0.1.1 yourhost.example.com yourhost", which is a common configuration, getaddrinfo is only going to return 127.0.1.1.
This snippet will give a list of all available IPV4 addresses in the system.
import itertools
from netifaces import interfaces, ifaddresses, AF_INET
links = filter(None, (ifaddresses(x).get(AF_INET) for x in interfaces()))
links = itertools.chain(*links)
ip_addresses = [x['addr'] for x in links]
I think @Harley Holcombe's answer is workable, but if you have some virtual NICs without ip it will error. so this is i modified:
def get_lan_ip():
for interface in interfaces():
try:
for link in ifaddresses(interface)[AF_INET]:
if str(link['addr']).startswith("172."):
return str(link['addr'])
except:
pass
this will only return your lan ipv4