Finding local IP addresses using Python's stdlib under Debian jessie
I am writing a distributed systems program in python, and in this program I need to know the local ip-address... eg. 168.192.... 10.13..... etc, not 127.0.0.1 or hostname.
I have found following solution on stackoverflow
https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
import socket
socket.gethostbyname(socket.gethostname())
When I run this on my Debian jessie laptop, I get 127.0.0.1, however, my friend who is using Fedora on his machine gets the desired ip address when he runs the same script (eg. 168.192..)
I prefer to use the solution above if possible to get the local ip address, because most of the other proposed solutions are either hacks or incredible long...
Is there something I can setup on my Debian jessie laptop such that python will return the correct local ip-address?
- using debian jessie
- python 3
- is connected to network (.. and computer is turned on)... ;)
- /etc/hosts currently contains:
127.0.0.1 localhost
127.0.0.1 debianASUS
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Solution 1:
The most reliable way to find the IP address your host will use to communicate is by using getsockname
on a connected UDP socket. In case of UDP the connect
system call doesn't involve any network communication.
Here is a Python function I have written in the past for a similar purpose. If you don't know in advance which remote IP address you will communicate with, you should be looking for one which will be using the default route. If you already know which remote IP address you will communicate with, then it is better to use that IP address in the connect call.
def my_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('192.0.0.8', 1027))
except socket.error:
return None
return s.getsockname()[0]
With a few minor changes, this function can be adapted to return an IPv6 address rather than IPv4:
def my_ipv6():
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
s.connect(('2001:db8::', 1027))
except socket.error:
return None
return s.getsockname()[0]
Solution 2:
Have you considered defering the decision to the end user at runtime, through a configuration parameter ? This is a standard practice for this problem.
The reason is there is no systematic foolproof way to figure "the" local IP address (a host may be multihomed, may be running a v4/v6 dual stack, a VPN, etc..). Runtime configuration will make the sysadmin's job easier !